Commit Graph

18153 Commits

Author SHA1 Message Date
Eileen M. Uchitelle ff309346d3
Merge pull request #49268 from ghiculescu/cpk-guide
Add Composite Primary Keys guide to guides index
2023-09-14 11:39:14 -04:00
Alex 25524826aa Add Composite Primary Keys guide to guides index 2023-09-14 12:32:33 +10:00
Nikita Vasilevsky dcfddc1f90
Explicit `primary_key:` option should always take priority in associations
This commit fixes the issue where the `primary_key:` option was ignored
if the associated model had a `query_constraints` configured.
Now `primary_key:` option always takes priority and only if there is no
`primary_key:` option, the `query_constraints` are used to determine
the `association_primary_key` value.
2023-09-13 21:12:04 +00:00
Daniel Colson cf8ab2f4b8
Add outcome to transaction tracking payload
Following up on https://github.com/rails/rails/pull/49192, this commit
adds the transaction `outcome` to the payload, helpful for collecting
stats on how many transactions commit, rollback, restart, or (perhaps
most interestingly) are incomplete because of an error.

The one quirk here is that we have to modify the payload on finish. It's
not the only place this sort of thing happens (instrument mutates the
payload with exceptions, for example), but it does mean we need to dup
the payload we initialize with to avoid mutating it for other tracking.

Co-authored-by: Ian Candy <ipc103@github.com>
2023-09-13 15:30:50 -04:00
eileencodes 86a5f33bbe
Don't pass active_record to `derive_fk_query_constraints`
We already have access to the `active_record` on the reflection here so
there's no point in passing it to `derive_fk_query_constraints`.

In addition the id, fk check wasn't actually doing anything here, it was
holdover from debugging I was doing when implementing this
functionality.
2023-09-13 10:35:19 -04:00
Rafael Mendonça França 699dfdb426
Preparing for 7.1.0.beta1 release 2023-09-13 00:36:01 +00:00
Alex 439c93ed74 Encryption: support `support_unencrypted_data` being set at a per-attribute level 2023-09-12 16:13:47 +10:00
Daniel Colson ce49fa9b31 Instrument Active Record transactions
Tracking Active Record-managed transactions seems to be a common need,
but there's currently not a great way to do it. Here's a few examples
I've seen:

* GitHub has custom transaction tracking that monkey patches the Active
  Record `TransactionManager` and `RealTransaction`. We use the tracking
  to prevent opening a transaction to one database cluster inside a
  transaction to a different database cluster, and to report slow
  transactions (we get slow transaction data directly from MySQL as well,
  but it's still helpful to report from the application with backtraces to
  help track them down).
* https://github.com/palkan/isolator tracks transactions to prevent
  non-atomic interactions like external network calls inside a
  transaction. The gem works by subscribing to `sql.active_record`, then
  piecing together the transactions by looking for `BEGIN`, `COMMIT`,
  `SAVEPOINT`, etc., but this is unreliable:
    - https://github.com/palkan/isolator/issues/65
    - https://github.com/palkan/isolator/issues/64
* It looks like GitLab patches `TransactionManager` and `RealTransaction`
  to track nested savepoints. See https://github.com/palkan/isolator/issues/46

This commit adds a new `transaction.active_record` event that should
provide a more reliable solution for these various use cases. It
includes the connection in the payload (useful, for example, in
differentiating transactions to different databases), but if this change
gets merged we're also planning to add details about what type of
transaction it is (savepoint or real) and what the outcome is (commit,
rollback, restarted, errored).

This instrumentation needs to start and finish at fairly specific times:
  - start on materialize
  - finish after committing or rolling back, but before the after_commit
    or after_rollback callbacks
  - finish and start again when the transaction restarts (at least for
    real transactions—we've done it for savepoints as well but I'm not
    certain we should)
  - ensure it finishes if commit and rollback fail (e.g. if the
    connection goes away)
To make all that work, this commit uses the lower-level `#build-handle`
API instead of `#instrument`.

Co-authored-by: Ian Candy <ipc103@github.com>
2023-09-11 20:43:09 -04:00
Jonathan Hefner 0a453330d7 Fix ActiveRecord::TokenFor documentation [ci-skip]
RDoc was confused by the placement of `:nodoc:`, causing it to skip the
documentation for `ActiveRecord::TokenFor#generate_token_for` (though
not the documentation for `ActiveRecord::TokenFor::ClassMethods`).

Also, RDoc supports `<b>` tags but not `<strong>` tags.  (Though,
ironically, it converts `<b>` tags to `<strong>` tags when rendering.)
2023-09-10 16:45:56 -05:00
Jonathan Hefner 843283b4dd Add negative `where` examples for `normalizes`
In #49105, `where` examples were added to the `normalizes` documentation
to demonstrate that normalizations are also applied for `where`.
However, as with the `exists?` examples, we should also demonstrate that
normalizations are only applied to keyword arguments, not positional
arguments.  We can also address the original source of the confusion by
changing the wording of "finder methods" to "query methods".

This commit also removes the tests added in #49105.  `normalizes` works
at the level of attribute types, so there is no need to test every query
method.  Testing `find_by` is sufficient.  (And, in point of fact,
`find_by` is implemented in terms of `where`.)
2023-09-10 16:40:29 -05:00
Rafael Mendonça França 845bc7ce1c
Avoid default value
This method is internal so we can just always pass the argument.
2023-09-09 20:28:04 +00:00
Rafael Mendonça França 35f85a3aa1
Make branches explict
We only set the column to a single column if the primary key is a single
value, so move that code to an explicit else.
2023-09-09 20:27:13 +00:00
fatkodima 3f17465362
Support composite foreign keys via migration helpers 2023-09-09 20:24:41 +00:00
Ryuta Kamizono 234eff4cbc
Merge pull request #49178 from ccutrer/add_check_constraint_if_not_exists
Adds support for `if_not_exists` when adding a check constraint.
2023-09-09 11:06:57 +09:00
Ryuta Kamizono 2d4ea403f0
Merge pull request #49177 from ccutrer/remove_check_constraint_if_exists_fix
Fix `remove_check_constraint` with `if_exists: true` never removing any check constraint
2023-09-09 10:50:20 +09:00
Nikita Vasilevsky 43d1db0d35
Fix typo in id_value docs 2023-09-07 17:39:01 +00:00
Cody Cutrer bb783cad08 Adds support for `if_not_exists` when adding a check constraint.
The `add_check_constraint` method now accepts an `if_not_exists` option. If set to true an error won't be raised
if the check constraint already exists. In addition, `if_exists` and `if_not_exists` options are transposed
if set when reversing `remove_check_constraint` and `add_check_constraint`. This enables simple creation
of idempotent, non-transactional migrations.
2023-09-06 14:54:59 -06:00
Jean Boussier 304f0a3c01
Merge pull request #49173 from Shopify/define-alias-attribute-methods-in-define_attribute_methods
Define alias attribute methods in `define_attribute_methods`
2023-09-06 22:53:43 +02:00
Cody Cutrer e02ac345e8 Fix `remove_check_constraint` with `if_exists: true` never removing any check constraint
It was never finding existing constraints, because `CheckConstraintDefinition` was
validating all options--including `if_exists`--matched.
2023-09-06 14:07:40 -06:00
Nikita Vasilevsky 0f5563bd40
Define alias attribute methods in `define_attribute_methods`
`undefine_attribute_methods` now removes alias attribute methods along
with attribute methods. This commit changes `define_attribute_methods` to
redefine methods back if any alias attributes were declared which provides
applications and libraries an option to bring the alias methods back
after using `undefine_attribute_methods`.
2023-09-06 20:06:39 +00:00
Jean Boussier 9044d35c2f
Merge pull request #49166 from aleksclark/ensure-identical-dump-files
ensure identical md5 sums for gzip schema cache
2023-09-06 20:00:59 +02:00
Gannon McGibbon 6debd54d24
Merge pull request #49156 from gmcgibbon/cpk_fixtures
Add composite primary key examples to fixture docs
2023-09-06 12:11:06 -05:00
Gannon McGibbon cd1289d30b [skip ci] Add composite primary key examples to fixture docs
It isn't clear how to associate composite primary key table fixtures,
so let's add an example to ActiveRecord::FixtureSet's documentation.
2023-09-06 11:39:59 -05:00
Joshua Young 0a54155757
[Fix #49055] Raise an `ArgumentError` when `#accepts_nested_attributes_for` is redeclared for an association 2023-09-06 15:27:59 +00:00
Aleks Clark 56e1ecdb56
set mtime = 0 in schema gz dump in order to ensure identical md5 sums for identical contents 2023-09-06 05:36:31 -05:00
Eileen M. Uchitelle 20df3820a0
Merge pull request #49154 from Shopify/query-constraints-option-in-associations
Document `query_constraints` option in associations
2023-09-05 14:09:03 -04:00
Nikita Vasilevsky 96d3cca6d8
[ci skip] Document `query_constraints` option in associations 2023-09-05 17:54:16 +00:00
Adrianna Chang 2fdd1ad670
Infer primary_key: :id on associations with composite primary key models
Previously, a composite primary key model would need to specify
either a `primary_key` or `query_constraints` option on its associations.
Without it, a `CompositePrimaryKeyMismatchError` would be raised.

Most of the time, the composite primary key includes the `:id` column,
and associations already expect that `:id` is being used as the
primary key for the association (and have a corresponding foreign_key
column set on the associated model).

Rather than requiring users to define `primary_key: :id` throughout
an application with composite primary key associations, we can infer
that the `:id` column should be used. Users can still override this
behaviour by specifying a `primary_key:` or `query_constraints:` on
the association.

Note that, if the composite primary key for a model does _not_ include
`:id`, Rails won't infer the primary key for any related associations,
and users must still specify `query_constraints` or `primary_key`.

Prior to this change, you'd need to do the following to set up
associations for composite primary key models:

```ruby
class Order
  self.primary_key = [:shop_id, :id]

  has_many :order_agreements, primary_key :id
end

class OrderAgreement
  belongs_to :order, primary_key: :id
end
```

After this change, the `primary_key` option no longer needs to be
specified:

```ruby
class Order
  self.primary_key = [:shop_id, :id]

  has_many :order_agreements
end

class OrderAgreement
  belongs_to :order
end
```
2023-09-05 12:12:57 -04:00
Eileen M. Uchitelle ad83a66b70
Merge pull request #49116 from gmcgibbon/where_tuple_docs
Document tuple support in Active Record where clauses
2023-09-05 11:31:54 -04:00
Gannon McGibbon 6d165124cd [skip ci] Document tuple support in Active Record where clauses
Adds documentation to ActiveRecord::QueryMethods#where mentioning tuple
syntax support added in #47729.
2023-09-05 10:15:43 -05:00
Ryuta Kamizono 2df70ddb96 Generate secure token only once regardless of `on: :initialize` or `on: :create`
Follow-up to #47420.

Whereas the original behavior (`on: :create`) is invoked only once
before a record is persisted, the new behavior (`on: :initialize`) is
invoked not only new record but also persisted records.

It should be invoked only once for new record consistently.
2023-09-05 17:43:41 +09:00
Ryuta Kamizono 2fbb25b771
Merge pull request #49133 from fatkodima/fix-has_secure_token-when-not-selected-column
Fix `has_secure_token on: :initialize` when column is not selected
2023-09-05 15:25:16 +09:00
Ryuta Kamizono ca374bd9a3
Merge pull request #49136 from fatkodima/fix-counter-caches-var-modification
Fix in-place modification of shared `_counter_cache_columns` class attribute
2023-09-05 15:07:52 +09:00
fatkodima 2933e16528 Fix in-place modification of shared `_counter_cache_columns` class attribute 2023-09-04 19:32:48 +03:00
fatkodima 72e3a3c9c1 Fix `assert_deprecated` related warnings in ActiveRecord tests 2023-09-04 16:25:20 +03:00
fatkodima 32f43176bb Fix `has_secure_token on: :initialize` when column is not selected 2023-09-04 15:55:57 +03:00
Ryuta Kamizono 8271186d01 Merge pull request #48095 from ippachi/triple-dot-range-unscope
Fix unscope not working when where by tripe dot range
2023-09-04 17:16:25 +09:00
Ryuta Kamizono 532188cbf4
Merge pull request #45498 from HParker/deprecate-rewhere-on-merge
Deprecate passing `rewhere` to `merge`
2023-09-04 16:03:42 +09:00
Sean Doyle e85a3ec624
Change `has_secure_token` default to `on: :initialize`
Follow-up to [#47420][]

With the changes made in [#47420][], `has_secure_token` declarations can
be configured to execute in an `after_initialize` callback. This commit
proposed a new Rails 7.1 default: generate all `has_secure_token` values
when their corresponding models are initialized.

To preserve pre-7.1 behavior, applications can set
`config.active_record.generate_secure_token_on = :create`.

By default, generate the value when the model is initialized:

```ruby
class User < ApplicationRecord
  has_secure_token
end

record = User.new
record.token # => "fwZcXX6SkJBJRogzMdciS7wf"
```

With `config.active_record.generate_secure_token_on = :create`, generate
the value when the model is created:

```ruby
 # config/application.rb
config.active_record.generate_secure_token_on = :create

 # app/models/user.rb
class User < ApplicationRecord
  has_secure_token on: :create
end

record = User.new
record.token # => nil
record.save!
record.token # => "fwZcXX6SkJBJRogzMdciS7wf"
```

[#47420]: https://github.com/rails/rails/pull/47420

Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
2023-09-01 20:17:22 +00:00
Eileen M. Uchitelle 3bc64016af
Merge pull request #49112 from gmcgibbon/cpk_id_docs
Composite Primary Key id method docs
2023-09-01 15:58:54 -04:00
Эдем 7c65a4b83b
Make enums validatable without raising error (#49100)
* Make enums validatable without raising error

* Trigger fail CI

Co-authored-by: Rafael Mendonça França <rafael@rubyonrails.org>
2023-09-01 15:31:12 -04:00
Gannon McGibbon 5ae1c5a812 [skip ci] Document id_value method
Adds documention for ActiveRecord::ModelSchema#id_value as a utility
when using composite primary keys.
2023-09-01 14:15:02 -05:00
Gannon McGibbon 362134b462 [skip ci] Document composite primary key behaviour
Adds documentation to exaplain composite key behaviour in
ActiveRecord::AttributeMethods::PrimaryKey for
methods #id, #id=, #id?, #id_before_type_cast, #id_was, #id_in_database.
2023-09-01 14:14:43 -05:00
Rafael Mendonça França cdbc9b78cb
Merge pull request #49090 from skipkayhil/hm-change-column-precision-6
Fix change_column not setting precision for sqlite
2023-09-01 14:21:53 -04:00
Jean Boussier 9fd3d03dab
Merge pull request #49105 from Earlopain/ar-normalizes-where
Document `where` support for AR `normalizes`
2023-09-01 19:02:14 +02:00
Hartley McGuire 57a9e25f8e
Fix change_column not setting precision for sqlite
There were a few 6.1 migration compatibility fixes in [previous][1]
[commits][2]. Most importantly, those commits reorganized some of the
compatibility tests to ensure that the tests would run against every
Migration version. To continue the effort of improving test coverage for
Migration compatibility, this commit converts tests for create_table and
change_column setting the correct precision on datetime columns.

While the create_table tests all pass, the change_column test did not
pass for 7.0 versioned Migrations on sqlite. This was due to the sqlite
adapter not using new_column_definition to set the options on the new
column (new_column_definition is where precision: 6 gets set if no
precision is specified). This happens because columns can't be modified
in place in sqlite and instead the whole table must be recreated and the
data copied. Before this commit, change_column would use the options
of the existing column as a base and merge in the exact options (and
type) passed to change_column.

This commit changes the change_column method to replace the existing
column without using the existing options. This ensures that precision:
6 is set consistently across adapters when change_column is used to
create a datetime column.

[1]: c2f838e80c
[2]: 9b07b2d6ca
2023-09-01 16:57:19 +00:00
Nikita Vasilevsky 0aa4cc4bbc
[skip ci] Document using `FinderMethods.find` on composite primary key models 2023-09-01 16:15:41 +00:00
Earlopain 830957e213
Document `where` support for AR `normalizes`
Also some other small changelog tweak:
* Add normalize_value_for to the activerecord changelog
* Fix a wrong method reference in the 7.1 release notes
2023-09-01 18:13:23 +02:00
Jean Boussier 9a1d465438 Fix `ActiveRecord.disconnect_all!` to not disable reconnect on pools
Followup: https://github.com/rails/rails/pull/47856
2023-09-01 16:59:17 +02:00
Filinto Romain 14a34c7223 fix class_name STI 2023-09-01 10:55:28 +02:00
eileencodes 6297e60d3b
Fix alias_attribute deprecation warning and message
I noticed this test was throwing a warning for `alias_attribute
:id_value, :id` defined by Rails. Since this test messes with primary
keys I decided to fix it by making custom classes for each of the
tests that need to change the PK.

While debugging these tests I noticed the deprecation wasn't formatted
correctly so I fixed that while in there.
2023-08-31 15:36:37 -04:00
Eileen M. Uchitelle 411bfa2734
Merge pull request #49088 from eileencodes/derive-foreign-key-query-constraints
Allow Active Record to derive the association query constraints
2023-08-31 12:08:05 -04:00
eileencodes a332dd9323
Allow Active Record to derive the association query constraints
Active Record already has the ability to guess the foreign key. With
query constraints we can use the information from the owner class and
that foreign key to infer what the query constraints should be for an
association. This change improves the ergonomics of the query
constraints feature by making it so that you only have to define the
query constraints on the top level model and skip defining it on the
association. There are a few caveats to this as of this PR:

- If the query constraints on the parent are greater than 2, Rails can't
derive the association constraints
- If the query constraints on the parent don't include the primary key,
Rails can't derive the association constraints.
- If the association has an explicit `foreign_key` or
`query_constraints` option set, Active Record won't infer the key.
- I have not implemented support for CPK yet as it's more complex and
maybe not possible since we don't know which key to split on and use
for the foreign association.

Prior to this change you would need to do the following to use query
constraints:

```ruby
class Post
  query_constraints :blog_id, :id

  has_many :comments, query_constraints: [:blog_id, :blog_post_id]
end

class Comment
  query_constraints :blog_id, :id

  belongs_to :blog, query_constraints: [:blog_id, :blog_post_id]
end
```

After this change, the associations don't require you to set the query
constraints, Active Record will generate `[:blog_id, :blog_post_id]`
foreign key itself.

```ruby
class Post
  query_constraints :blog_id, :id

  has_many :comments
end

class Comment
  query_constraints :blog_id, :id

  belongs_to :blog
end
```
2023-08-31 11:12:59 -04:00
Jean Boussier a7fdc1cdb4 Optimize ActiveRecord::LogSubscriber#query_source_location
`Kernel#caller` has linear performance based on how deep the
stack is. While this is a development only feature, it can end
up being quite slow.

Ruby 3.2 introduced `Thread.each_caller_location`, which lazily
yield `Backtrace::Location` objects.

Ref: https://bugs.ruby-lang.org/issues/16663

This is perfect for this use case as we are searching for the
closest frame that matches a pattern, saving us from collecting
the entire backtrace.
2023-08-31 11:56:55 +02:00
emily.qiu 3af0c0108d Allow KILL queries on read-only connections for mysql 2023-08-30 14:58:56 -05:00
Ian Candy eae26caec3 Clarify deprecation warning for alias_attribute
We ran into a few cases at GitHub where we were using alias_attribute
incorrectly and the new behavior either didn't warn or raised an unclear
deprecation warning. This attempts to add clarity to the deprecation reason
when you try to alias something that isn't actually an attribute.

Previously, trying to alias a generated attribute method, such as `attribute_in_database`, would
still hit `define_proxy_call`, because we were only checking the owner of the target method.

In the future, we should probably raise if you try to use alias_attribute for a non-attribute.

Note that we don't raise the warning for abstract classes, because the attribute may be implemented
by a child class. We could potentially figure out a way to raise in these cases as well, but this
hopefully is good enough for now.

Finally, I also updated the way we're setting `local_alias_attributes` when `alias_attribute` is
first called. This was causing problems since we now use `alias_attribute` early in the
`load_schema!` call for some models: https://buildkite.com/rails/rails/builds/98910
2023-08-30 13:19:58 -04:00
Greg Molnar c775fa4db5 upsert should accept update_only parameter like upsert_all does 2023-08-28 16:59:24 +00:00
paulreece 4026aba1f1 This branch fixes the issues raised in #48862. By adding the key and it's values to self.references_values as Rails does when building a where clause, it prevents unneccessary aliasing from taking place and allows a User to successfully use a table_alias in their select query using a Hash. 2023-08-25 17:53:59 -04:00
Rafael Mendonça França d70707d9af
Merge pull request #49020 from Shopify/allow-redefining-to-param-delimiter
Allow redefining `to_param` delimiter using `param_delimiter`
2023-08-23 18:11:14 -04:00
Rafael Mendonça França 59542e86c4
Merge pull request #49019 from adrianna-chang-shopify/ac-deprecate-read-attribute-id-pk
Deprecate `read_attribute(:id)` returning the primary key
2023-08-23 18:02:36 -04:00
Rafael Mendonça França c70ac1d9eb
Merge pull request #49012 from skipkayhil/hm-migration-table-def-methods
Ensure all migration versions use TableDefinition
2023-08-23 17:59:41 -04:00
Nikita Vasilevsky 564a3d6d97
Support composite primary key in `AR::Base#to_param` 2023-08-23 21:53:47 +00:00
Adrianna Chang ac83311bae
Deprecate `read_attribute(:id)` returning the primary key
This commit deprecates `read_attribute(:id)` returning the primary key
if the model's primary key is not the id column. Starting in Rails 7.2,
`read_attribute(:id)` will always return the value of the id column.

This commit also changes `read_attribute(:id)` for composite primary
key models to return the value of the id column, not the composite
primary key.
2023-08-23 16:36:32 -04:00
Adrianna Chang a5f64bf29d
Merge pull request #49004 from andrewn617/improve-base-class-documentation
Improve the documentation for ActiveRecord::Inheritance#base_class
2023-08-23 09:36:12 -04:00
Andrew Novoselac 46279956cf Improve the documentation for ActiveRecord::Inheritance#base_class 2023-08-23 09:19:40 -04:00
Jean Boussier be2c6320f1
Merge pull request #48996 from Shopify/check-for-parent-being-an-owner-of-the-target-method
Allow parent being the owner of an alias attribute method
2023-08-23 14:33:00 +02:00
Nikita Vasilevsky 0c99588919
Allow parent being the owner of an alias attribute method
When an abstract class inherited from an Active Record model
defines an alias attribute Rails should expect the original methods
of the aliased attribute to be defined in the parent class and avoid
raising deprecation warning.
2023-08-23 11:35:45 +00:00
Hartley McGuire c793cdc665
Ensure all migration versions use TableDefinition
This is similar to a [previous commit][1] which ensures that versioned
migrations always call `super` in `compatible_table_definition`. In this
case, these methods are being pulled up to `Current` so that all
subclasses will use a `TableDefinition` class and future developers do
not have to remember to add all of these methods to new versioned
classes when a new one is created.

[1]: 16f8bd7944
2023-08-23 02:03:31 -04:00
Hartley McGuire 9b07b2d6ca
Fix 6.1 change_table setting datetime precision
While working on #48969, I found that some of the Compatibility test
cases were not working correctly. The tests removed in this commit were
never running the `change_table` migration and so were not actually
testing that `change_table` works correctly. The issue is that the two
migrations created in these tests both have `nil` versions, and so the
Migrator only runs the first one.

This commit refactors the tests so that its easier to test the behavior
of each Migration class version (and I think the rest of the tests
should be updated to use this strategy as well). Additionally, since the
tests are fixed it exposed that `t.change` in a `change_table` is not
behaving as expected so that is fixed as well.
2023-08-22 14:01:52 -04:00
Rafael Mendonça França ed5af00459
Merge pull request #48998 from Shopify/to_key-supports-composite-primary-key
Support composite identifiers in `to_key`
2023-08-22 13:53:19 -04:00
Nikita Vasilevsky 8a5cf4cf44
Support composite identifiers in `to_key`
This commit adds support for composite identifiers in `to_key`.
Rails 7.1 adds support for composite primary key which means that
composite primary key models' `#id` method returns an `Array` and
`to_key` needs to avoid double-wrapping the value.
2023-08-22 16:13:23 +00:00
Jean Boussier 5f6c404853
Merge pull request #48983 from JoeDupuis/fix-regression-on-strict-has-one-through
Fix regression blocking creation of some strict association
2023-08-22 17:20:56 +02:00
Hartley McGuire c2f838e80c
Fix 6.1 change_column setting datetime precision
This is already the case for add_column and create_table, but
change_column was missed
2023-08-21 19:10:14 -04:00
Rafael Mendonça França ccee593fed
Merge pull request #48930 from adrianna-chang-shopify/ac-id-value
Use `alias_attribute` to provide `id_value` alias for `id` attribute
2023-08-21 14:33:39 -04:00
Adrianna Chang e90b11e77e
Use alias_attribute to provide #id_value alias for #id
This allows access to the raw id column value on records for which an
id column exists but is not the primary key. This is common amongst
models with composite primary keys.
2023-08-21 14:12:53 -04:00
Rafael Mendonça França 6beb3482cd
Merge pull request #48991 from andrewn617/fix-alias-attribute-on-superclass
Fix defect where aliased attribute methods on abstract classes were not being defined
2023-08-21 13:55:46 -04:00
Andrew Novoselac 211146b845 Fix defect where aliased attribute methods on abstract classes were being not defined
rails/rails@a88f47d fixed an issue where subclasses were regenerating aliased attribute methods defined on parent classes. Part of the solution was to call #generate_alias_attributes recursively on a class's superclass to generate all the alias attributes in the inheritance hierarchy. However, the implementation relies on #base_class to determine if we should call #generate_alias_attributes on the superclass. Since all models that inherit from abstract classes are base classes, this means that #generate_alias_attributes will never be called on abstract classes, meaning no method will be generated for any alias attributes defined on them.

To fix this issue, we should always call #generate_alias_attributes on the superclass unless the superclass is ActiveRecord::Base.
2023-08-21 13:32:26 -04:00
Joé Dupuis 4b3571803b Fix regression blocking creation of some strict association
PR #48606 introduced a regression preventing the creation of a chain
of models using a has_one through association when strict_loading is
activated.

The association relies on the initial stale_state being `nil`
to skip loading the target.
755c13f167/activerecord/lib/active_record/associations/association.rb (L175)

PR #48606 initializes the stale_state to `[nil]`
https://github.com/rails/rails/pull/48606/files#diff-39c3da3c5f3fbff01b0a32d3b7ec613fda6bc6225fdbe2629134d91babe37786R84-R86

This change converts the `[nil]` state back to `nil`.
2023-08-21 10:32:08 -07:00
Rafael Mendonça França 77080d5e17
Initialize @has_query_constraints to false in the inherited hook
`has_query_constraints?` is a class method so doing it in init_internals
would not define the right variable.
2023-08-21 15:58:58 +00:00
Guillermo Iguaran 4ec3a986d5
Merge pull request #48959 from skipkayhil/hm-clean-filters-requires
Remove uneeded requires of core_ext/string/filters
2023-08-18 16:03:44 -07:00
Rafael Mendonça França ce36426c98
Initialize the variable in the init_internals method
This will avoid that the conditional assignment is executed every time
has_query_constraints? is called.
2023-08-18 22:13:14 +00:00
eileencodes 3b5a4a56fb
Fix uninitialized ivar 2023-08-18 13:30:51 -04:00
eileencodes 784ca88173
Add method for accessing only query constraints
I'm working on an enhancement to query constraints that will require me
to know when we have query constraints but not a composite key.
Currently if you have a composite key it will be included in the query
constraints list. There's not a way to differentiate between the two
which means that we're forced into setting the query constraints on the
associations for the primary key.

This change adds a `has_query_constraints?` method so we can check the
class for query constraints. The options still work as well but we can
be sure we're always picking up the query constraints when they're
present.
2023-08-18 13:21:06 -04:00
Eileen M. Uchitelle ac5f9dec53
Merge pull request #48947 from eileencodes/use-IN-sql-over-OR-with-query-constraints
Use IN sql instead of OR sql for query constraints
2023-08-17 15:34:31 -04:00
eileencodes 0bbf4e86cb
Use IN sql intead of OR sql for query constraints
We originally implemented this project to use OR queries instead of IN
because it seemed like there was no way to do that without a row
constructor. While working on implementing this feature in our vitess
gem I noticed that we can actually get the queries we wanted, and the
new code is more performant than generating an OR.

SQL Before:

```sql
SELECT "sharded_comments".*
FROM "sharded_comments"
WHERE ("sharded_comments"."blog_id" = 969142904
AND ("sharded_comments"."blog_post_id" = 357271355
OR "sharded_comments"."blog_post_id" = 756811794)
OR "sharded_comments"."blog_id" = 308674288
AND "sharded_comments"."blog_post_id" = 1055755181)
```

SQL After:

```sql
SELECT "sharded_comments".*
FROM "sharded_comments"
WHERE "sharded_comments"."blog_id"
IN (969142904, 308674288)
AND "sharded_comments"."blog_post_id"
IN (357271355, 756811794, 1055755181)
```

Using one of the tests that utilizes this code path, I benchmarked the
queries. The new implementation is faster:

Before:

```
Warming up --------------------------------------
             queries   147.000  i/100ms
Calculating -------------------------------------
             queries      1.486k (± 3.2%) i/s -      7.497k in   5.050742s
```

After:

```
Warming up --------------------------------------
             queries   179.000  i/100ms
Calculating -------------------------------------
             queries      1.747k (± 4.5%) i/s -      8.771k in   5.031424s
```

We can probably improve this more but I think this query is more in line
with what we want and expect while also being more performant (without
having to build a new row constructor in arel).
2023-08-17 15:04:32 -04:00
Eileen M. Uchitelle b56f938b5f
Merge pull request #48964 from sinsoku/fix-method-name
Fix method name to `check_all_pending!`
2023-08-17 10:04:41 -04:00
Eileen M. Uchitelle 8abfcd752a
Merge pull request #48913 from ipc103/fix-parent-deprecation-warning
Allow parent to define alias method override
2023-08-17 09:46:26 -04:00
Takumi Shotoku 0e41e2cd8e
Fix method name to `check_all_pending!`
The method added in 03379d1f59 is `check_all_pending!`, not
`check_pending_migrations!`.
2023-08-17 16:51:39 +09:00
Ian Candy a88f47d012 Only define attribute methods for class
Because we're using a class_attribute to track all of the attribute_aliases,
each subclass was regenerating the parent class methods, causing some unexpected
deprecation messages.

Instead, we can use a class instance variable to track the attributes aliased locally
in that particular subclass. We then walk up the chain and re-define the attribute methods
if they haven't been defined yet.
2023-08-16 18:23:02 -04:00
Hartley McGuire ff6e885d59
Remove uneeded requires of core_ext/string/filters
`actionpack/lib/action_dispatch/routing.rb`
- added: 013745151b
- removed: 93034ad7fe

`activejob/lib/active_job/log_subscriber.rb`
- added: b314ab555e
- removed: 5ab2034730

`activemodel/lib/active_model/errors.rb`
- added: cf7fac7e29
- removed: 9de6457ab0

`activerecord/lib/active_record/core.rb`
- added: b3bfa361c5
- removed: e1066f450d

`activesupport/lib/active_support/core_ext/module/introspection.rb`
- added: 358ac36edf
- removed: 167b4153ca

`activesupport/lib/active_support/duration.rb`
- added: 75924c4517
- removed: a91ea1d510

`railties/lib/rails/commands/server/server_command.rb`
- added: f217364893
- removed: 553b86fc75

`railties/lib/rails/command/base.rb`
- added: 6813edc7d9
- removed: b617a561d8
2023-08-16 17:39:25 -04:00
Rafael Mendonça França b6669e5605
Merge pull request #48927 from paulreece/remove_table_alias_writer
This removes the writer method for table_alias from Arel::Table.
2023-08-11 15:34:18 -04:00
paulreece 6b56de4183 This removes the writer method for table_alias from Arel::Table. Since arel_table is a private API of the framework, no one should be modifying it. 2023-08-10 20:20:13 -04:00
zzak 81fa9136f8
Merge pull request #48924 from skipkayhil/hm-docs-fix-plusses
Fix code blocks using + instead of <tt> [ci skip]
2023-08-11 08:04:19 +09:00
Hartley McGuire bac6d8c079
Fix code blocks using + instead of <tt>
Pluses cannot be used to create code blocks when the content includes a
space.

Found using a regular expression:

```bash
$ rg '#\s[^+]*\+[^+]*\s[^+]*\S\+'
```
2023-08-10 13:05:05 -04:00
Eileen M. Uchitelle 22fa76c125
Merge pull request #48911 from jhbabon/fix/schema-cache-settings
Ensure schema_cache_dump settings are propagated to SchemaReflection class
2023-08-10 10:57:57 -04:00
Nikita Vasilevsky 594f539324
Use `ActiveRecord.deprecator` for the alias attribute deprecation 2023-08-09 20:51:23 +00:00
Juan Hernández Babón d5984f4d80 Ensure schema_cache_dump settings are propagated to SchemaReflection class 2023-08-09 14:11:44 +02:00
Robert DiMartino eceaa38e06
Fix tracking previous changes for ActiveRecord::Store accessors with underlying JSON data column 2023-08-07 22:26:45 -04:00
John Hawthorn 3cb00edea5
Merge pull request #48879 from jhawthorn/get-rid-of-trilogy-errors-merge
Get rid of trilogy errors merge
2023-08-03 23:17:19 -07:00
Rafael Mendonça França e6521dcb2b
No need for local variable for relation 2023-08-04 02:23:03 +00:00
Rafael Mendonça França c1817e468b
Extract private method to batch on unloaded relation
This will make the in_batches differences between loaded and unloaded
relations.
2023-08-04 02:21:43 +00:00
Rafael Mendonça França 94efd65fdf
Extract private method to implement batch on loaded relation
Isolate the behavior so it is clear what in `in_batches` is reposible
for this logic.
2023-08-04 02:10:41 +00:00
Rafael Mendonça França 2e3df04fcb
Merge pull request #48873 from drnic/arel-cast-function
Adds Arel::FactoryMethods#cast(node, type)
2023-08-03 21:52:00 -04:00
John Hawthorn 08d58e77ed Merge remote-tracking branch 'Shopify/get-rid-of-trilogy-errors' 2023-08-03 16:06:02 -07:00
Rafael Mendonça França fbaba19e2d
Merge PR #48608 2023-08-03 19:29:30 +00:00
Eileen M. Uchitelle db6159ce62
Merge pull request #48861 from paulreece/correct_missing_and_associated_behavior
Fixes #47909 when using order or unscope
2023-08-03 11:26:37 -04:00
Jean Boussier 147a715790
Merge pull request #48876 from HParker/warn-and-reduce-queries-on-loaded-relations
Use already loaded relation when batching if possible
2023-08-03 09:57:56 +02:00
Dr Nic Williams 32bdff49fe Adds Arel::FactoryMethods#cast(node, type)
For example:
  product_table = Product.arel_table
  product_table.cast(product_table[:position], "integer")

Produces SQL:
  CAST(position as integer)
2023-08-03 17:50:18 +10:00
HParker db92fb7b70 Use already loaded relation when batching if possible
If you have already loaded the relation when using in_batches, you
would reload each batch from the database.  Since we already have the
records available, we can avoid these queries and return the records
as-if the query was run.
2023-08-03 00:07:34 -07:00
zzak b2c53f8f9f
Revert "Merge pull request #48413 from fatkodima/fix-autosave-association-with-validation-on-save"
This reverts commit 655278edeb, reversing
changes made to 43852db088.
2023-08-02 19:53:53 +00:00
paulreece 4aa339cbbe This fix corrects the logic in both the associated and missing methods. If the reflection.options hash has a key/value pair for :class_name it will use the association. This fixes 48651 which was not returning the correct value when using an enum association and querying for a record that had one key of the enum but was missing another. This also fixes 44964 where ActiveRecord was not properly aliasing self-referencing relations. If the reflection.options doesn’t contain the key/value pair then it will use the reflection.table_name. This fixes 47909 in which a user was trying to find records that were either missing a relation or were missing a relation that was ordered or unscoped or were missing a relation that was using extends in the query which resulted in an ActiveRecord Exception. It also allows for using extends in any of these capacities. 2023-08-02 11:47:13 -04:00
Rafael Mendonça França 834aa41242
Merge PR #48740 2023-08-01 23:05:45 +00:00
Rafael Mendonça França a2e6f952ed
Merge pull request #48808 from zzak/revert-create-association-breaking-changes
Revert singular association breaking changes
2023-08-01 19:01:36 -04:00
Eileen M. Uchitelle 98e12fc6d6
Merge pull request #48852 from f3ndot/issue-37779-escape-literal-colons-2
Allow escaping of literal colons in `ActionRecord::Sanitization#replace_named_bind_variables`
2023-08-01 10:38:04 -04:00
Jean Boussier 35a614c227
Merge pull request #48793 from Shopify/define-attributes-initializer
Never connect to the database in define_attribute_methods initializer
2023-08-01 08:45:24 +02:00
Justin Bull 694376f15e Allow use of backslashes to escape literal colons
Despite the inconvenience of double-backslashing, the backslash was chosen
because it's a very common char to use in escaping across multiple programming
languages. A developer, without looking at documentation, may intuitively try
to use it to achieve the desired results in this scenario.

Fixes #37779
2023-07-30 07:55:02 -04:00
Juan Hernández Babón c4c28846e0 Use connection.schema_version inside ActiveRecord::SchemaCache
AbstractAdapter#schema_version uses migration_context.current_version by
default, but some adapters might redefine this method to use a custom
schema version number. This fix ensures that generated schema cache
files use this method and that it is also used when validating a file's
version.
2023-07-28 16:47:57 +02:00
Eileen M. Uchitelle 40a9d9bea1
Merge pull request #48738 from paulreece/enum_join_missing_fix
Restores functionality to the missing method when using enums and fixes #48651
2023-07-27 14:18:53 -04:00
paulreece 7aed2ca84a This fix corrects the logic in both the associated and missing methods. If the @scope.values has more than one key it will use associated in the WHERE IS NOT NULL SQL clause. This fixes 48651 which was not returning the correct value when using an enum association and querying for a record that had one key of the enum but was missing another. This also fixes 44964 where ActiveRecord was not properly aliasing self-referencing relations. If the @scope.values has only one key it will use reflection.table_name in the WHERE IS NOT NULL SQL clause. This fixes 47909 in which a user was trying to find records that were simply missing a relation which resulted in an ActiveRecord Exception. 2023-07-27 12:19:52 -04:00
Jean Boussier 3c7f48b8b9 Sort SchemaCache members when dumping it
Ref: https://github.com/rails/rails/issues/42717

This allow to result to be consistent, allowing to use its digest
for cache keys and such.
2023-07-27 10:29:56 +02:00
Nikita Vasilevsky 6798b43bef
Return `false` early when a non-AR object passed to `FinderMethods#include?`
This PR fixes a bug introduced in https://github.com/rails/rails/pull/48761
which leads to a `NoMethodError` when a non Active Record object passed
to `include?` or `member?` since only Active Record objects
respond to `composite_primary_key?`.
2023-07-26 18:05:50 +00:00
zzak 2e0c302df3
Revert "Merge pull request #46386 from lazaronixon/fix-has-one-create-record"
This reverts commit d2cb5b7469, reversing
changes made to 348e609da3.
2023-07-26 14:52:31 +09:00
zzak 09c1a85ab7
Revert "Merge pull request #48416 from Shopify/fix-has-one-deletion"
This reverts commit 6be41aded8, reversing
changes made to 55c3066da3.
2023-07-26 14:51:17 +09:00
Adrianna Chang 7981988fa0
Fix #previously_new_record? on destroyed records
Ref: #48794

`#previously_new_record?` should return false for records that are
created and then destroyed.
2023-07-25 15:49:49 -04:00
Eileen M. Uchitelle 06e8bb5b4c
Merge pull request #48795 from Shopify/tweak-alias-attribute-deprecation-message
Tweak `alias_attribute` deprecation message
2023-07-25 10:51:13 -04:00
Nikita Vasilevsky 408b1b95d4
Tweak `alias_attribute` deprecation message 2023-07-25 13:53:55 +00:00
Xavier Noria b70571c3c0
Update activerecord/lib/active_record/errors.rb
Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
2023-07-24 19:31:38 +02:00
Jean Boussier 5f3eb2195b
Merge pull request #48773 from nirvdrum/thread-safe-quoted-names
Make ActiveRecord's quoted name caches thread-safe on JRuby/TruffleRuby
2023-07-24 18:17:50 +02:00
Kevin Menard 68d572a5d1 Make ActiveRecord's quoted name caches thread-safe. 2023-07-24 12:04:10 -04:00
Jean Boussier de765e37c1 Never connect to the database in define_attribute_methods initializer
Followup: https://github.com/rails/rails/pull/48743

After careful consideration, unless users have a schema cache dump loaded
and `check_schema_cache_dump_version = false`, we have no choice but
to arbitrate between resiliency and performance.

If we define attribute methods during boot, we allow them to be shared
between forked workers, and prevent the first requests to be slower.

However, by doing so we'd trigger a connection to the datase, which
if it's unresponsive could lead to workers not being able to restart
triggering a cascading failure.

Previously Rails used to be in some sort of middle-ground where
it would define attribute methods during boot if for some reason
it was already connected to the database at this point.

But this is now deemed undesirable, as an application initializer
inadvertantly establishing the database connection woudl lead to
a readically different behavior.
2023-07-24 16:37:50 +02:00
Xavier Noria 4dd55e8d81
Update activerecord/lib/active_record/errors.rb
Co-authored-by: Hartley McGuire <skipkayhil@gmail.com>
2023-07-21 18:35:39 +02:00
Xavier Noria 7970c8af12 Improve the docs of ActiveRecord::TransactionRollbackError 2023-07-21 18:06:07 +02:00
Jean Boussier 3ee73bff39
Merge pull request #48533 from Shopify/delay-alias-attribute-defition
Call proxy methods from `alias_attribute` generated methods
2023-07-21 14:08:30 +02:00
Xavier Noria 5a36344334 Fixes the documentation of with_transaction_returning_status
This method was refactored in d916c62, but the documentation was not updated.
2023-07-21 13:07:55 +02:00
John Hawthorn 4c7f792371
Merge pull request #48766 from ywenc/ywenc/add-other-to-method
Call `other.value_for_database` in ActiveRecord::Relation::QueryAttribute == check
2023-07-19 17:38:17 -07:00
ywenc 7941511e48
Fix `StatementCache::Substitute` with serialized type (#48765)
* Don't call value_for_database if StatementCache::Substitute

Test type.dump with string

Co-authored-by: jhawthorn <jhawthorn@github.com>

* Update query_attribute.rb

Co-authored-by: jhawthorn <jhawthorn@github.com>

* Use double quotes

---------

Co-authored-by: jhawthorn <jhawthorn@github.com>
2023-07-19 17:37:51 -07:00
ywenc 8358008bb9 Call other.value_for_database in == check
Co-authored-by: jhawthorn <jhawthorn@github.com>
2023-07-19 17:40:35 -04:00
Jean Boussier 47d0f4ec0f Add a missing word in a comment 2023-07-19 17:32:29 +02:00
Eileen M. Uchitelle 5faf31bd6b
Merge pull request #48761 from adrianna-chang-shopify/ac-fix-include-method-cpk
Support `include?` and `member?` on composite primary key relations
2023-07-19 10:39:42 -04:00
Adrianna Chang 15f91c5963
Support include? and member? on composite primary key relations
`include` and `member?` delegate to `exists?` with the record's primary
key to determine if an unloaded relation contains a given record. If
the primary key is composite, `exists?` belives we are passing
where-style conditions and fails.

This commit fixes the issue by turning the record's composite primary key
into a hash of column / value pairs that `exists?` can accept.
2023-07-19 09:16:30 -04:00
Gregory Jones 4837bcaeef
Merge branch 'main' into postgres-index-nulls-not-distinct 2023-07-18 15:05:24 -04:00
Sean Doyle 7d63864486 Specify when to generate `has_secure_token`
The callback when the value is generated. When called with `on:
:initialize`, the value is generated in an `after_initialize` callback,
otherwise the value will be used in a `before_` callback. It will
default to `:create`.
2023-07-18 14:48:30 -04:00
Jean Boussier 835eb8a213
Merge pull request #48743 from Shopify/ar-define-attr-methods-init
Cleanup `define_attribute_methods` initializer
2023-07-18 10:21:50 +02:00
Nikita Vasilevsky 1818beb3a3
Call proxy methods from `alias_attribute` generated methods
This commit changes bodies of methods generated by `alias_attribute`
along with generating these methods lazily.

Previously the body of the `alias_attribute :new_title, :title` was
`def new_title; title; end`. This commit changes it to
`def new_title; attribute("title"); end`.

This allows for `alias_attribute` to be used to alias attributes named
with a reserved names like `id`:
```ruby
  class Topic < ActiveRecord::Base
    self.primary_key = :title
    alias_attribute :id_value, :id
  end

  Topic.new.id_value # => 1
```
2023-07-17 22:22:28 +00:00
Jorge Manrubia e6d59cdebb
Fix queries for deterministically encrypted attributed for data migrated from 7.0. (#48676)
#48530 introduced a problem for the system that extends AR queries involving deterministically encrypted attributes. The problem is that this option added the same "previous scheme" for all the attributes, when the only intended ones were the "non deterministic" ones. A side effect of this is that, when encrypting query param values, it was using the wrong encryption scheme.

Fixes https://github.com/rails/rails/issues/48204#issuecomment-1623301440
2023-07-17 19:38:54 +02:00
Jean Boussier 7e07fde9a3 Cleanup `define_attribute_methods` initializer
Followup: https://github.com/rails/rails/pull/48716

`model.connection_pool.schema_reflection` is never falsy, so that `if`
was pointless.

Instead we more properly check if the schema cache contains that table.

I also added some more comments to explain why the initializer tries
so hard not to touch the database.
2023-07-17 16:45:22 +02:00
Jean Boussier 13cff7e197
Merge pull request #48716 from Shopify/schema-reflection
Refactor Active Record Schema Cache to not hold a connection
2023-07-17 12:14:46 +02:00
Jonathan Hefner 04fede8cb7 Fix comment syntax [ci-skip] 2023-07-16 15:19:31 -05:00
Nick Dower b563cabc60 Discard connection in ensure, not rescue
Partially Fixes #48164. Followup to #48200.

`within_new_transaction` currently discards connections if an error
is raised which may have left the connection in a transaction. This change
updates that logic to discard connections in an `ensure` block to handle
cases where an error is not raised, for instance if the thread is killed.
2023-07-15 10:05:56 +02:00
Matthew Draper b36f9186b0 Refactor Active Record Schema Cache to not hold a connection
A big problem with the current `SchemaCache` implementation is that it holds
a reference to a connection, and uses it to lazily query the schema when the
information is missing.

This cause issues in multi-threaded contexts because all the connections
of a pool share the same schema, so they are constantly setting themselves
as the connection the schema cache should use, and you can end up in
situation where Thread#1 query the schema cache, which end up using the
connection currently attributed to Thread#2.

For a very long time this worked more or less by accident, because all
connection adapters would have an internal Monitor.

However in https://github.com/rails/rails/pull/46519 we got rid of this
synchronization, revealing the pre-existing issue. Previously it would
work™,  but still wasn't ideal because of unexpected the connection
sharing between threads.

The idea here is to refactor the schema cache so that it doesn't hold a
reference onto any connection.

And instead of a `SchemaCache`, connections now have access to a
`SchemaReflection`. Now the connection that needs a schema information
is always provided as an argument, so that in case of a miss, it can be
used to populate the cache.

That should fix the database thread safety issues that were witnessed.

However note that at this stage, the underlying `SchemaCache` isn't
synchronized, so in case of a race condition, the same schema query
can be performed more than once. It could make sense to add synchronization
in a followup.

This refactoring also open the door to query the cache without a connection,
making it easier to eagerly define model attribute methods on boot without
establishing a connection to the database.

Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
Co-Authored-By: zzak <zzakscott@gmail.com>
2023-07-13 12:34:13 +02:00
Jacopo 186474f273 Fix counter_cache create/concat with overlapping counter_cache_column
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>
2023-07-13 12:06:08 +02:00
Jean Boussier 29205d7928 Eagerly cast serialized query attributes
Fix: https://github.com/rails/rails/issues/48652
Ref: https://github.com/rails/rails/pull/46048
Ref: https://github.com/rails/rails/issues/46044
Ref: https://github.com/rails/rails/pull/34303
Ref: https://github.com/rails/rails/pull/39160
Close: https://github.com/rails/rails/pull/48705

This deep_dup was introduced to prevent the value stored in the query
cache to be later mutated.

The problem is that `ActiveRecord::Base#dup` will return a copy
of the record but with the primary key set to nil. One could
argue that `#dup` shouldn't behave this way, but I think this ship
has sailed (or has it?).

My initial fix was to instead always call `type.cast` eagerly so that we'd dup
serialized types in a more correct way. However there is a test
that explictly ensure this doesn't happen: https://github.com/rails/rails/pull/39160

The reason isn't 100% clear to me, but if I get it correctly, it's to avoid
a potentially costly operation upfront.

So instead we only eagerly cast serialized attributes only, so protect against
future mutations.

Mutable types are still deep duped.
2023-07-13 11:44:33 +02:00
Eileen M. Uchitelle a8e653fdd0
Merge pull request #48724 from gmcgibbon/improve_cpk_validation_check
Improve cpk validation check
2023-07-12 18:12:01 -04:00
Gannon McGibbon 410fc35055 Remove unused suppress_composite_primary_key on HABTM join model class
This method appears to be dead code. Since it was intended to be
private, it should be safe to remove without deprecation.
2023-07-12 16:12:13 -05:00
Gannon McGibbon ab0451132c Improve CPK error message
A developer may not always want to specify query constraints. If, for
example they would like to use a non-composite primary key in an
asscoaition, they need to use primary_key/foreign_key options instead.

Co-authored-by: Nikita Vasilevsky <nikita.vasilevsky@shopify.com>
2023-07-12 16:02:46 -05:00
Gannon McGibbon c18d1293b3 Allow assocaition primary keys to be derived with query contraints
Support assignment of belongs_to associations with query constraints.
This improves errors messages for composite key mismatches, and some
edge cases with query constraint lists.

Co-authored-by: Nikita Vasilevsky <nikita.vasilevsky@shopify.com>
2023-07-12 16:02:45 -05:00
Gannon McGibbon b2c0f3e5c1 Validate composite key length when owner record class has composite key
Catches more bugs in CPK assocaitions by validating the shape of keys on
both ends of the association.

Co-authored-by: Nikita Vasilevsky <nikita.vasilevsky@shopify.com>
2023-07-12 15:40:15 -05:00
Petrik de Heus f768944bdf
Merge branch 'main' into activerecord/aes256gm-inspect 2023-07-11 21:10:42 +02:00
eileencodes 95f7feaf74
Remove connected? check from db_runtime payload
The check for `Base.connected?` was added in
4ecdf24bde.
At the time this change was made, we were calling
`Base.connection.reset_runtime` so it made sense to check if the
database was connected. Since
dd61a817de
we have stored that information in a thread instead, negating the need
to check `Base.connected?`.

The problem with checking `Base.connected?` is that in a multi-db
application this will return `false` for any model running a query not
inheriting from `Base`, leaving the `db_runtime` payload `nil`. Since
the information we need is stored in a thread rather than on the
connection directly we can remove the `Base.connected?` check.

Fixes #48687
2023-07-10 11:21:59 -04:00
Eileen M. Uchitelle 56c784d808
Merge pull request #48690 from adrianna-chang-shopify/ac-merge-target-list-cpk-fix
Prevent `#merge_target_lists` from clearing id column on composite primary key records
2023-07-10 09:06:07 -04:00
Jean Boussier 5fbaa524b9 Active Record commit transaction on `return`, `break` and `throw`
Fix: https://github.com/rails/rails/issues/45017
Ref: https://github.com/rails/rails/pull/29333
Ref: https://github.com/ruby/timeout/pull/30

Historically only raised errors would trigger a rollback, but in Ruby `2.3`, the `timeout` library
started using `throw` to interupt execution which had the adverse effect of committing open transactions.

To solve this, in Active Record 6.1 the behavior was changed to instead rollback the transaction as it was safer
than to potentially commit an incomplete transaction.

Using `return`, `break` or `throw` inside a `transaction` block was essentially deprecated from Rails 6.1 onwards.

However with the release of `timeout 0.4.0`, `Timeout.timeout` now raises an error again, and Active Record is able
to return to its original, less surprising, behavior.
2023-07-10 10:37:42 +02:00
Adrianna Chang c5abbbae59
Prevent #merge_target_lists from clearing id column on CPK records
Previously, when merging persisted and in-memory records, we were using
`record[name]` to get the value of the attribute. For records with a
composite primary key, the full CPK would be returned, which was
incompatible with `#_write_attribute`: we'd attempt to assign an Array
to the `id` column, which would result in the column being set to nil.

When dealing with a record with a composite primary key, we need to
write each part of the primary key individually via `#_write_attribute`.
2023-07-07 16:52:37 -04:00
eileencodes b69fa80b66
Deprecate `name` argument in `remove_connection`
The `name` argument is not useful as `remove_connection` should be called
on the class that established the connection. Allowing `name` to be
passed here doesn't match how any of the other methods behave on the
connection classes. While this behavior has been around for a long time,
I'm not sure anyone is using this as it's not documented when to use
name, nor are there any tests.
2023-07-06 15:55:35 -04:00
Petrik 7dd38cfa16 Don't show secrets for Active Record's `Cipher::Aes256Gcm#inspect`.
If anyone calls a cypher in the console it will show the secret of the
encryptor.

By overriding the `inspect` method to only show the class name we can
avoid accidentally outputting sensitive information.

Before:

```ruby
ActiveRecord::Encryption::Cipher::Aes256Gcm.new(secret).inspect
"#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038 ... @secret=\"\\xAF\\bFh]LV}q\\nl\\xB2U\\xB3 ... >"
```

After:

```ruby
ActiveRecord::Encryption::Cipher::Aes256Gcm(secret).inspect
"#<ActiveRecord::Encryption::Cipher::Aes256Gcm:0x0000000104888038>"
```
2023-07-06 21:41:27 +02:00
Eileen M. Uchitelle fc1886757d
Merge pull request #48674 from gmcgibbon/hmt_singular_fix
Fix has_one through singular building with inverse.
2023-07-06 09:09:28 -04:00
Ryuta Kamizono e552fca4a6
Merge pull request #48657 from alpaca-tc/fix-association-with-has-many-inversing
Fix de-duplication of unsaved records for `ActiveRecord::Associations::CollectionProxy#<<`
2023-07-06 14:37:07 +09:00
Gannon McGibbon 68e0dd2c83 Fix has_one through singular building with inverse.
Allows building of records from an association with a has_one through a
singular association with inverse. For belongs_to through associations,
linking the foreign key to the primary key model isn't needed.
For has_one, we cannot build records due to the association not being mutable.
2023-07-05 23:22:51 -05:00
alpaca-tc d413d36de2 Fix de-duplication of unsaved records for `ActiveRecord::Associations::CollectionProxy#<<`
The existing process was attempting to detect duplicates by storing added records in `Set.new`.
When a record is added to `Set.new`, the identity is calculated using `ActiveRecord::Core#hash`, but this value changes before and after saving, so duplicates were not detected before and after saving even for the same object.

This PR fixed the problem by using the `#object_id` of the record to detect duplicates.
Note that when storing a new object obtained by `ActiveRecord::Base.find` etc., duplicates are not eliminated because the `#object_id` is different. This is the same behavior as the current `ActiveRecord::Associations::CollectionProxy#<<`.
2023-07-06 09:51:55 +09:00
Gannon McGibbon 3fc9ade23b Make has_many through singular associations build CPK records
Adds support for building records in has_many through has_one
composite primary key associations.

Also updates query constraints on associations affected by rails/rails#48564.
2023-07-05 12:04:47 -05:00
Eileen M. Uchitelle d1a79da376
Merge pull request #48606 from gmcgibbon/stale_state_cpk
Support stale state detections in CPK through associations
2023-07-05 11:07:21 -04:00
eileencodes 5cf5a2af13
Fix parallel testing (issue #48547)
Fixes 2 bugs in parallel testing.

The first bug was related to changes made in #45450 which meant that we were
no longer replacing the connection in parallel testing because the
config object is equal (we simply merge a new db name but the object id
of the config stays the same). This bug only manifested in mysql and
sqlite3 interestingly. It would fail on the internal metadata tables
because they were missing in the schema version check.

To fix this I introduced a `clobber: true` kwarg onto the connection
handler that allows us to bypass the functionality that won't make a new
connection if the config is the same. This is an easy way to fall back
to the old behavior from before this change. I only added `clobber`
to the `reconstruct_from_schema` call because we need to actually
replace the connection for these. It's not safe to add everywhere since
we don't always want to replace the connection.

After implementing this fix I was still seeing failures in the mysql
demo app I made due to the fact that `purge` was not re-establishing the
connection to a config that had a database defined. Neither sqlite3 or
postgresql were missing this.

I added a test for mysql2 so we don't have regressions in the future. I
think this was missed because sqlite3 only demonstrates the bug if it
was never successful on that worker and postgresql was fine.

Fixes #48547
2023-07-05 10:50:54 -04:00
alpaca-tc 4c245bfd12 Fix a bug that prevented #pretty_print from displaying records unsaved in collection association.
The change in PR #43302 introduced a bug where unsaved records are not displayed in pretty_print.
The following code will not show unsaved records until this PR is merged.

```ruby
post = Post.create!
post.comments.build

pp(post.comments) #=> expected "[#<Post:0x000000014c0b48a0 ...>]", got "[]"
```

Fixed to call `#load_target` before display as well as `#inspect`.
2023-07-05 12:08:40 +09:00
Gannon McGibbon 755c13f167 Support stale state detections in CPK through associations
Stale states need to be tracked as arrays to properly check through
associations with composite primary keys.
2023-07-04 02:14:02 -05:00
zzak a234669d63
Disable database prepared statements when query logs are enabled
Fixes #48398

Prepared Statements and Query Logs are incompatible features due to query logs making every query unique.

Co-authored-by: Jean Boussier <jean.boussier@gmail.com>
2023-07-03 16:59:44 +09:00
Guillermo Iguaran b790387597
Merge pull request #48616 from p8/activerecord/document-dirty
Document `ActiveRecord::Dirty` module in the API docs
2023-06-30 13:07:13 -07:00
Rafael Mendonça França b2a99eee2b
Merge pull request #48506 from Shopify/rwstauner/fixture-set
Autoload ActiveRecord::FixtureSet
2023-06-30 13:32:43 -04:00
Petrik 4b3920ac9e Document `ActiveRecord::AttributeMethods::Dirty` module in the API docs
Currently it is a bit unclear which dirty methods can be called on
Active Record models. You have to know that methods from ActiveModel::Dirty
are included.

It also unclear if methods can be invoked in the form of
`saved_change_to_name?` unless you read the documentation of the
`saved_change_to_attribute?` method.

By adding an introduction to the module we can show which methods are
defined specifically for Active Record, and how to call them, very
similar to the ActiveModel::Dirty introduction.
Linking to ActiveModel::Dirty makes it's also easier to find methods
defined there.
2023-06-30 11:02:16 +02:00
Rafael Mendonça França e366af5bf5
Revert "Merge pull request #48487 from lazaronixon/scope-subqueries"
This reverts commit 6264c1de76, reversing
changes made to 6c80bcdd20.

Reason: Still discussion about the feature. We want to make it opt-in
but we need to better understand why people would want to opt-in to
this behavior.
2023-06-29 15:25:53 +00:00
Yasuo Honda b214c07558
Merge pull request #48594 from fatkodima/fix-pg-partial-index-on-keyword-column
Accept keyword-like named columns for PostgreSQL partial indexes
2023-06-29 23:15:26 +09:00
Gregory Jones 575a2e0ea7 Add index existence tests for nulls_not_distinct 2023-06-29 01:56:45 -04:00
Gregory Jones 10bad051a8 Support NULLS NOT DISTINCT in Postgres 15+ 2023-06-28 23:24:57 -04:00
Randy Stauner 9b8524c291
Autoload ActiveRecord::FixtureSet
When eager_load is enabled and something (like the frozen_record gem)
tries to load yaml files that use `ActiveRecord::FixtureSet.identify(...)`
we'll get an uninitialized constant error.

Move requires for constants in the ActiveRecord::FixtureSet namespace
to below the creation of the class to avoid circular requires.
See ActiveSupport::Deprecation for a similar instance of this:
7dd67dc285/activesupport/lib/active_support/deprecation.rb (L35-L54)
2023-06-28 16:49:46 -07:00
Gannon McGibbon e6af9f55e6
Merge pull request #48564 from gmcgibbon/use_id_pk_cpk_book
Use id in composite primary key of cpk book and fix related bugs
2023-06-27 13:02:20 -05:00
fatkodima 0288c5cae0 Accept keyword-like named columns for PostgreSQL partial indexes 2023-06-27 19:35:04 +03:00
Gannon McGibbon abb6b207c0 Use _read_attribute to properly query id?
Support primary key dirty tracking when ID is a composite
primary key with an id column.

Introduces `ActiveRecord::AttributeMethods::Query#_query_attribute`
to bypass id reader.
2023-06-26 15:33:30 -05:00
Gannon McGibbon 16a5bdc511 Use _read_attribute in ids method
Support calculating IDs for collection proxies
using composite id column values instead of the id reader.
2023-06-26 15:33:30 -05:00
Gannon McGibbon 8a33758e51 Use _read_attribute in [association]_ids writer
Supports id primary key assignment in [association]_ids writer
for composite primary keys.
2023-06-26 15:33:30 -05:00
Matthew Hirst 00ebbbd746
This allows Rails projects with multiple databases to specify which database they would like the migrations to be copied to. 2023-06-26 19:27:47 +02:00
Rafael Mendonça França 5d81a7e6f8
Merge pull request #48507 from szymonlipka/fix-empty-string-range
Fix empty string saving for ranges
2023-06-26 12:05:06 -04:00
Rafael Mendonça França 587cc9b8ef
Merge pull request #47827 from shouichi/remove-class-cache
Remove ActiveRecord::FixtureSet::ClassCache
2023-06-26 12:04:09 -04:00
Jorge Manrubia 4f365720d1
Fix Active Record encryption not picking up encryption settings with eager-loading (#48577)
This deals with a problem where, when eager-loading is enabled, Active Record fails to pick up settings affecting encryption schemes.

The solution here is to resolve encryption schemes lazily, when the attribute type is used.

Follow-up from https://github.com/rails/rails/pull/48530

Closes https://github.com/rails/rails/issues/48204#issuecomment-1607127334
2023-06-26 13:25:38 +02:00
Jorge Manrubia c8d26bb647
Add a encryption option to support previous data encrypted non-deterministically with a SHA1 hash digest (#48530)
* Make sure active record encryption configuration happens after initializers have run

Co-authored-by: Cadu Ribeiro <mail@cadu.dev>

* Add a new option to support previous data encrypted non-deterministically with a hash digest of SHA1

There is currently a problem with Active Record encryption for users updating from 7.0 to 7.1 Before
#44873, data encrypted with non-deterministic encryption was always using SHA-1. The reason is that
`ActiveSupport::KeyGenerator.hash_digest_class` is set in an after_initialize block in the railtie config,
but encryption config was running before that, so it was effectively using the previous default SHA1. That
means that existing users are using SHA256 for non deterministic encryption, and SHA1 for deterministic
encryption.

This adds a new option `use_sha1_digest_for_non_deterministic_data` that
users can enable to support for SHA1 and SHA256 when decrypting existing data.

* Set a default value of true for `support_sha1_for_non_deterministic_encryption` and proper initializer values.

We want to enable the flag existing versions (< 7.1), and we want it to be false moving by
default moving forward.

* Make sure the system to auto-filter params supports different initialization orders

This reworks the system to auto-filter params so that it works when encrypted
attributes are declared before the encryption configuration logic runs.

Co-authored-by: Cadu Ribeiro <mail@cadu.dev>

---------

Co-authored-by: Cadu Ribeiro <mail@cadu.dev>
2023-06-25 10:16:22 +02:00
Gannon McGibbon 1ba823d662
Merge pull request #48552 from gmcgibbon/fix_cpk_hmt
Add support for unpersisted CPK has_one/has_many through associations
2023-06-23 14:42:20 -05:00
zzak dd89f600f7
🔗 Remove RDoc auto-link from Rails module everywhere 2023-06-23 10:49:30 +09:00
Gannon McGibbon 699a3725ad Add support for unpersisted CPK has_one/has_many through associations
Fixes loading of has_one and has_many associations with composite
primary key though associations that have unpersisted owner records.
2023-06-21 17:15:04 -05:00
Gannon McGibbon 622485ae4b Add support for nullifying CPK has_one associations
Composite primary key records need to conditionally unset multiple
column attributes from the associated record in order to properly
support dependent: nullify.
2023-06-21 11:08:06 -05:00
Szymon Lipka ca170d8161 Fix empty string range saving 2023-06-21 09:23:41 +02:00
Guillermo Iguaran 119b4b2af1 Fix the name of delegated method for the records to Array#intersect?
The right method name is Array#intersect?

This adds a test case to avoid this mistake in the future.
2023-06-20 22:22:58 -07:00
Alex Ghiculescu 657600c4d6 Revert "Revert "Merge pull request #48527 from ghiculescu/active-record-enum-id"" 2023-06-21 08:56:13 +10:00
Guillermo Iguaran 6499ccbd09
Merge pull request #48534 from skipkayhil/hm-revert-48527
Revert "Merge pull request #48527 from ghiculescu/active-record-enum-id"
2023-06-20 15:41:12 -07:00
Aaron Patterson 6264c1de76
Merge pull request #48487 from lazaronixon/scope-subqueries
Apply scope to association subqueries
2023-06-20 15:07:29 -07:00
Hartley McGuire 96a86cb630
Revert "Merge pull request #48527 from ghiculescu/active-record-enum-id"
This reverts commit 8b36095881, reversing
changes made to e05245db87.

Railties tests have been failing since this change. The issue is that
calling `primary_key` as the model is loaded requires either a
connection to the database or a populated schema cache. This becomes an
issue when an app loads models that do not have underlying tables, as
shown in the failing Railties tests.

When eager loading an app using `rails/all`,
`ActionMailbox::InboundEmail` will be loaded whether or not `rails g
action_mailbox:install` has been run. This means the `primary_key` for
`InboundEmail` will not be in the schema cache and a database connection
will be required to boot the app.
2023-06-20 17:44:36 -04:00
zzak 9cdc347342
Fixup AR::FixtureSet docs
* Improve the spacing of various paragraphs
* Link to AS::TestCase.fixture_paths= API
* Add a note about needing to require "rails/test_help" to get fixture_paths
* Expanded briefly on YAML default map unordering property
* Improve heading weight consistency
* Unlink several RDoc autolinked things
2023-06-20 15:47:13 +09:00
zzak 4a63d94a24
Fix AR::TestFixtures.fixture_paths= docs
This removes the deprecated .fixture_path and .fixture_path= methods
from public documentation, and creates a class method for the getter and
setters.

Interestingly because these methods were always `class_attribute` based,
which RDoc doesn't parse, they weren't technically "public"
documentation.
2023-06-20 15:47:07 +09:00
Alex a22b942fb3 Disallow `id` as an enum value in Active Record
Fixes https://github.com/rails/rails/issues/48524

The test case in the issue breaks because `value.respond_to?(:id)` returns true [here](51f2e2f80b/activerecord/lib/active_record/relation/predicate_builder.rb (L58)). This effectively adds a default scope to queries where it shouldn't.

There might be a way to fix this in Active Record but I'd be surprised if nothing else breaks from defining `id` instance and class methods. I think it is simpler to not allow it as a value since it really should be treated as a reserved method.
2023-06-20 11:22:30 +10:00
Gannon McGibbon 51f2e2f80b
Merge pull request #48519 from adrianna-chang-shopify/ac-tweak-fixture-path-deprecations
Fix deprecation warning messages for `ActiveSupport::TestFixtures`
2023-06-19 17:32:13 -05:00
Adrianna Chang 0da4b8f315
Fix deprecation warning messages for test fixtures
Minor fixes to the deprecation messages around TestFixtures.fixture_path,
TestFixtures.fixture_path=, and TestFixtures#fixture_path to clarify
which method is deprecated and which should be used instead.
2023-06-19 10:09:52 -04:00
Nixon 8d520e0359 Apply scope to association subqueries 2023-06-16 15:48:24 -03:00
Eileen M. Uchitelle f97e867a22
Merge pull request #48490 from gmcgibbon/eager_load_cpk
Eager load composite primary keys models
2023-06-16 14:09:38 -04:00
Eileen M. Uchitelle 2f833a64ae
Merge pull request #48489 from gmcgibbon/_read_attribute_has_one_autosave
Use _read_attribute when autosaving has_one associations
2023-06-16 14:09:04 -04:00
Adrianna Chang 4b6fb72199
Bugfix: Ensure has_one associations saved when part of CPK has changed
If a has_one association uses a composite primary key, and part of the
composite primary key changes on the owner, these changes need to be
reflected on the belonging object's foreign key.

This was not working previously, because `#_record_changed?` was not
equipped to handle composite primary key associations, so we were not
recognizing that the belonging object's foreign key needed to be updated
when the owner's primary key changed.
2023-06-15 17:44:04 -04:00
Gannon McGibbon c18a95e38e Add support for eager loading cpk has_many/has_one relations
Correctly assigns eagerly loaded associations to composite primary key models.
2023-06-15 16:31:29 -05:00
Gannon McGibbon 4d04775920 Use _read_attribute when autosaving has_one associations
In models with composite primary keys, the #id accessor will return an
array, where we actually want the id column value.
2023-06-15 15:52:09 -05:00
Gannon McGibbon 145d2568fd Add support for eager loading cpk belongs_to relations
Correctly assigns eagerly loaded associations to composite primary key
models.
2023-06-15 15:17:53 -05:00
Eileen M. Uchitelle 8a4543d739
Merge pull request #48484 from adrianna-chang-shopify/ac-composite-primary-key-associations-inverse
Fix setting inverses for composite primary key associations
2023-06-15 14:03:18 -04:00
Adrianna Chang 4e53fd0aad
Fix setting inverses for composite primary key associations
Checking whether a record has a foreign key for a composite primary key
association requires us to check whether all parts of the foreign key
are present. Otherwise, the inverse association will not be set.
2023-06-15 13:30:19 -04:00
Ray Faddis ce6047f84f Adding PG enum rename, add value, and rename value migration helpers 2023-06-15 10:03:23 -04:00
Nikita Vasilevsky 892e4ae24c
Fix `destroy_all` for `has_many :through` associations that points to a CPK model 2023-06-14 17:48:13 +00:00
ippachi ed680483db
Fix unscope not working when where by tripe dot range
Fix #48094
2023-06-14 01:15:08 +09:00
Varun Sharma 2a8475c6d1 Remove unnecessary splat operator 2023-06-13 19:51:25 +05:30
Eileen M. Uchitelle a14c5f07e1
Merge pull request #48436 from gmcgibbon/cpk_malformed_key
Add better TypeError when assigning CPK
2023-06-12 12:40:16 -04:00
Eileen M. Uchitelle 716baea69f
Merge pull request #48440 from fatkodima/fix-batching-using-cpk
Fix ActiveRecord batching over composite primary keys
2023-06-12 09:24:09 -04:00
a5-stable 6538d65b04 wrap Arel.sql to avoid error 2023-06-12 00:43:35 +09:00
Varun Sharma f0712f39d4 Do not revalidate encrypted attribute with current encrypted_type 2023-06-11 19:39:14 +05:30
fatkodima 14cfad3137 Fix ActiveRecord batching over composite primary keys 2023-06-10 18:20:25 +03:00
Gannon McGibbon 13b495bfd0 Add better TypeError when assigning CPK
Raises a more readable error when assigning a singular ID to a
model with a composite primary key.
2023-06-09 13:16:14 -05:00
Jenny Shen b202d5be99
Handle ER_DBACCESS_DENIED_ERROR code in mysql2 adapter
During the process of adding adapter tests to test the different types of connection errors,
the ER_DBACCESS_DENIED_ERROR code was discovered to be not handled. It is the same as
ER_ACCESS_DENIED_ERROR except that a database has been given.

https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_dbaccess_denied_error

Co-authored-by: Adrianna Chang <adrianna.chang@shopify.com>
2023-06-09 10:26:36 -04:00
Jean Boussier ec1aa50a89 Revert "Merge pull request #48406 from rails/revert-46790-singular-association-refactor"
This reverts commit f6f2b2d53f, reversing
changes made to 3e01b26a16.
2023-06-07 10:02:59 +02:00
Yasuo Honda 655278edeb
Merge pull request #48413 from fatkodima/fix-autosave-association-with-validation-on-save
Fix autosave associations with validations added on `:base` of the associated objects
2023-06-07 11:14:05 +09:00
fatkodima d01c4a7045 Fix autosave associations with validations added on `:base` of the associated objects 2023-06-07 02:07:53 +03:00
Nikita Vasilevsky 257f0124fc
Allow composite primary key to be derived from schema
This commit stops issuing the
"Active Record does not support composite primary key" warning
and allows `ActiveRecord::Base#primary_key` to be derived as an `Array`
2023-06-06 14:39:04 +00:00
Eileen M. Uchitelle e7be1e76bc
Merge pull request #48400 from adrianna-chang-shopify/ac-scope-for-create-on-cpk
Fix `#scope_for_create` for belongs_to associations with CPK
2023-06-06 09:04:22 -04:00
Jean Boussier 7f1c93bd19
Revert "Small refactor on build singular association" 2023-06-06 14:33:01 +02:00
Matthew Draper 3e01b26a16 Merge pull request #48295 from luanzeba/connection_attr_reader
Store `connection_pool` in database-related exceptions
2023-06-06 20:33:55 +09:30
Adrianna Chang e684588e53
Fix `#scope_for_create` for belongs_to associations with CPK
`#scope_for_create` for singular associations removes the primary key
from the scope so that we don't assign PK columns when building an
association.

However, removing the primary key from the scope doesn't currently
handle composite primary keys. This commit fixes that.
2023-06-05 17:06:12 -04:00
Eileen M. Uchitelle 768ebf9985
Merge pull request #48385 from adrianna-chang-shopify/ac-autosave-belongs-to-destroy
Fix destroying belongs_to associations for CPK
2023-06-05 13:33:01 -04:00
takuyaK 9452b59506 Support batching using composite primary keys and multiple column ordering
When find_each/find_in_batches/in_batches are performed on a table with composite primary keys, ascending or descending order can be selected for each key.

    ```ruby
    Person.find_each(order: [:desc, :asc]) do |person|
      person.party_all_night!
    end
    ```
2023-06-05 21:59:38 +09:00
Rafael Mendonça França fb919dac93
Merge pull request #47647 from fatkodima/remove_unique_key-by-options
Consider options when removing UNIQUE KEYs
2023-06-02 16:56:01 -04:00
Adrianna Chang be231a7f22
Fix destroying belongs_to associations for CPK
This commit handles destroying CPK associations when autosave is set
and the parent association is marked for destruction. It does so
by ensuring that all parts of the foreign key (the parent's CPK)
are set to nil before destroying the parent record.
2023-06-02 15:39:33 -04:00
Gannon McGibbon 87c2ad0a81 Fix has_one autosaving for CPK associations
Adds support for autosaving has_one associations with composite primary keys.
2023-06-02 11:20:53 -05:00
Luan Vieira 7d4c88dde3
Store connection_pool in DB exceptions
Anytime an exception is raised from an adapter we now provide a
`connection_pool` along for the application to further debug what went
wrong. This is an important feature when running a multi-database Rails
application.

We chose to provide the `connection_pool` as it has relevant context
like connection, role and shard. We wanted to avoid providing the
`connection` directly as it might accidentally be used after it's
returned to the pool and been handed to another thread.
The `ConnectionAdapters::PoolConfig` would also have been a reasonable
option except it's `:nodoc:`.
2023-06-02 10:44:28 -04:00
Eileen M. Uchitelle 254f1d8ded
Merge pull request #48357 from gmcgibbon/belongs_to_cpk
Add composite primary key validity check on belongs_to associations.
2023-06-02 08:25:16 -04:00
Gannon McGibbon f9a8f9c976 Add composite primary key validity check to associations.
Raise ActiveRecord::CompositePrimaryKeyMismatchError when a belongs_to,
has_one, or has_many foreign key and primary key don't have the same length.
2023-06-02 01:32:59 -05:00
Nixon aa41938e3a Fix polymorphic association subquery 2023-06-02 02:50:23 -03:00
Yasuo Honda 95af5fce71
Merge pull request #45783 from shhavel/fix/anonymous_pg_columns_of_different_type_from_json
[AR] Fix result with anonymous PG columns of different type from json
2023-06-02 08:33:08 +09:00
eileencodes 2c39149e99
Revert deprecation message for prepared statements
While we had hoped to turn prepared statements on for Rails 7.2, the bug
that's preventing us from doing that is still present. See #43005.

Until this bug is fixed we should not be encouraging applications
running mysql to change the `prepared_statements` in the config to
`true`. In addition to this bug being present, Trilogy does not yet
support `prepared_statements` (although work is in progress).

It will be better to implement this deprecation when mysql2 and trilogy
can both handle `prepared_statements` without major bugs.
2023-06-01 16:11:55 -04:00
Nikita Vasilevsky c92933265e
Assign auto populated columns on Active Record object creation
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.
2023-06-01 14:39:12 +00:00
eileencodes 7d60710559
Add role to connection payload
It doesn't make sense to include shard if we're also not going to
include role.
2023-05-31 15:59:21 -04:00
Eileen M. Uchitelle ced5e77936
Merge pull request #48353 from eileencodes/set-default-shard-from-connects_to-hash
Set default_shard from connects_to hash
2023-05-31 15:29:57 -04:00
eileencodes 0d41bfd3cc
Set default_shard from connects_to hash
If an application is using sharding, they may not want to use `default`
as the `default_shard`. Unfortunately Rails expects there to be a shard
named `default` for certain actions internally. This leads to some
errors on boot and the application is left manually setting
`default_shard=` in their model or updating their shards in
`connects_to` to name `shard_one` to `default`. Neither are a great
solution, especially if Rails can do this for you. Changes to Active
Record are:

* Simplify `connects_to` by merging `database` into `shards` kwarg so we
can do a single loop through provided options.
* Set the `self.default_shard` to the first keys in the shards kwarg.
* Add a test for this behavior
* Update existing test that wasn't testing this to use `default`. I
could have left this test but it really messes with connections in the
other tests and since this isn't testing shard behavior specifically, I
updated it to use `default` as the default shard name.

This is a slight change in behavior from existing applications but
arguably this is fixing a bug because without this an application won't
boot. I originally thought that this would require a huge refactoring to
fix but realized that it makes a lot of sense to take the first shard as
they default. They should all have the same schema so we can assume it's
fine to take the first one.

Fixes: #45390
2023-05-31 12:52:12 -04:00