Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make insert return an array, and include the id_value if super returns nil (12) #2381

Merged
merged 21 commits into from
Aug 13, 2024

Conversation

andynu
Copy link
Contributor

@andynu andynu commented Mar 31, 2024

Make insert return an array, and include the id_value if super returns nil

ActiveRecord::ConnectionAdapters::OracleEnhanced::DatabaseStatements#insert
The super here is not returning the id_value if it is available (as it used
to). Furthermore ActiveRecord::Persistence#_create_record expects an
array of values.

I don't think this is the right change. In fact I think that the original abstract
ActiveRecord::ConnectionAdapters::DatabaseStatements#insert
may not be handling id_value correctly. The method appears to sometimes return
an array, and other times return a singular id_value.

However, I do think this highlights the crux of supporting rails 7.1 in this library as with this little tweak, all the tests passing against rails 7-1-stable.

This fixes #2380

Introduce the _connection method which returns whichever is defined
between @unconfigured_connection or @raw_connection.
verify! ensures that @raw_connection is defined.
Rails commit bd19d1baf1 [1] added a check of logger.level which was not
supported by the MockLogger.

This commit adds a mock level method. And limits the missing_method to
respond only to logging calls, so any other calls will raise a
NoMethodError to make future debugging easier.

[1]
rails/rails@bd19d1b
The SchemaMigration object no longer inherits from ActiveRecord::Base.

See "Move SchemaMigration to an independent object"
rails/rails@436277d

Several methods were renamed, and are no longer available as class
methods on SchemaMigration, but as an instance of SchemaMigration
per connection.

The object per connection seems to remove the need to `reset_table_name`
in the tests. That method is not available on the new object.
Rails commit e6da3ebd6c6 [1] introduces ColumnDefinition validations for
the keywords used in database commands. This commit adds the additional
keywords supported by this gem.

[1] rails/rails@e6da3eb
@andynu andynu changed the title Make insert return an array, and include the id_value if super returns nil Make insert return an array, and include the id_value if super returns nil (12) Mar 31, 2024
@andynu andynu force-pushed the stack-12-sql-statement-args branch from 8da032a to 1d80f71 Compare March 31, 2024 02:39
See rails/rails@07d2407

Both `table_name` and `column_name` were removed in favor of doing
o.left in the visitor pattern. This is just mimicing the adjustments
from upstream.
@andynu andynu force-pushed the stack-12-sql-statement-args branch 2 times, most recently from ffc39e0 to fb1aae6 Compare April 1, 2024 16:00
andynu added 10 commits April 1, 2024 12:09
This extends the existing class level auto_retry functionality to
optionally allow an allow_retry boolean kwarg to allow retry of specific
queries.

This PR preserves the requirement that `autocommit?` be enabled which is the
safer choice.

```
  def with_retry(allow_retry: false) # :nodoc:
    should_retry = (allow_retry || self.class.auto_retry?) && autocommit?
```

See issue rsim#2310
See rails/rails@3682aa1

So the shortening of index names that was added to rails itself
was almost immediately changed to use an 'idx_' prefix instead of an 'ix_'
prefix.

See rails/rails@59f2b06

However, now that rails does shortening. It is an opportunity to
simplify this library and just rely on the rails index name shortening.
    DEPRECATION WARNING: Passing the class as positional argument is deprecated and will be removed in Rails 7.2.

    Please pass the class as a keyword argument:

      serialize :serialized, type: Array
     (called from <class:TestSerializedColumn> at /home/andy/src/oracle-enhanced/spec/active_record/connection_adapters/oracle_enhanced_adapter_spec.rb:446)
Rails removed the table_name alias to Arel::Table.name
See rails/rails@1d98bc5
In rails commit rails/rails@942785f

A method `internal_exec_query` is introduced as the implementation for
exec_query. For now this just aliases one to the other.
@andynu andynu force-pushed the stack-12-sql-statement-args branch from fb1aae6 to e58a68a Compare April 1, 2024 16:15
This is to accomodate rails commit rails/rails@3421e89

The trouble is primary keys are not returned with this code. The
Column#auto_incremented_by_db? method would have to return true for any
column with an associated sequence, or perhaps marked as the primary
key.
…s nil

The super is not returning the id_value if it is available (as it used
to). Furthermore ActiveRecord::Persistence#_create_record expects an
array of values.
@andynu andynu force-pushed the stack-12-sql-statement-args branch from e58a68a to e08c0d9 Compare April 1, 2024 18:21
@mattalat
Copy link

Hi @andynu, thank you for your PRs. I had a few questions.

  1. What is the intention of the 12 separate MRs? Do they provide different changes or are they all stacked in this twelfth one?

  2. There is a code comment that mentions needing to figure out if a column is a PK/auto-incremented. In "Assign auto populated columns on Active Record object creation", breaks the returning of id on insert #2380 you mention that this may have been fixed upstream. Is it still an ongoing concern?

  3. Regarding your notes on the structure of the abstract adapter’s #insert method, do you have a scenario to which you could direct me that showcases this behavior? The method’s documentation mentions it could return an Array of values if specific conditions are met, but I wasn’t sure if they are in Oracle. And, if it does seem like a bug on the adapter’s end, do you know if anyone has identified it in the Rails repo?

Thanks for your time

@andynu
Copy link
Contributor Author

andynu commented Apr 30, 2024

Hi @mattalat

  1. The Stack of PRs

The purpose of the stack of PRs is to show passing tests along the way. That does mean that each one in the stack contains the changes from the previous, and that this last one contains all the changes. As I mentioned in the rails 7.1 upgrade issue, I'd be happy to re-form these PRs as independent PRs instead of a stack, but with those you would not be able to see the passing tests because unresolved issues from other PRs would still be breaking the tests.

There are two ways to go about reviewing these changes. First we can go in order, that first PR is a minimal change on top of master, and if/when that one were merged in then the second PR in the stack would become simplified to just another small change. However, I acknowledge that some of these PRs may not be the implementation that the maintainers would like to use, in which case I would look at their fixes to rebase subsequent PRs on their changes. If you'd like the unstacked diff for any of these you need to do a comparison with the previous PR e.g. andynu/oracle-enhanced@stack-09-internal_exec_query...andynu:oracle-enhanced:stack-12-sql-statement-args (sorry that the branch names are not nicely numerically sequential, the bisecting to produce this stack of PRs was a challenging journey with many false starts and backpedaling).

  1. insert returning the id

So the issue in #2380 has been fixed in rails 7.2, and backported to 7.1. However, in this PR in DatabaseStatements#insert you can see Array(super || id_value) which I think is really working around a bug in rails, where super should be providing an array itself when an id_value is provided, but it doesn't it just returns whatever id_value is passed in, even though its api has changed to always expect an array to come out of it. I do think a better workaround involves adding support for OracleEnhanced::Column.auto_incremented_by_db?. I would put a pin in this one until the other fixes are sorted out, and then it'd be great to have a second set of eyes verify this fix /wrt issue #2381 and the upstream changes.

  1. test failures related to this pr

You can definitely see the failure. If you check out c043981 (That's one commit back in this PR), then you'll see a pile of test failures that illustrate the issue. I tried to have the meat of each of these PRs start with a version bump, and then a fix for the test failures that showed up. My stack of PRs here was explicitly chasing test failures of tests that already exist in this library as I bumped the rails version closer and closer to 7.1 stable.

@yahonda yahonda merged commit bc6b655 into rsim:master Aug 13, 2024
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

"Assign auto populated columns on Active Record object creation", breaks the returning of id on insert
3 participants