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

Support RETURNING clause for MariaDB #49840

Merged
merged 1 commit into from
Oct 31, 2023

Conversation

fatkodima
Copy link
Member

This is a rebased #49315 PR with addressed feedback.
I will need these changes for my effort of supporting uuid data type for MySQL/MariaDB.

I added a test case which tests that dynamic database defaults are populated after the INSERT. insert_all-like methods also support :returning, but these are already tested

skip unless supports_insert_returning?

Closes #49315.

cc @nvasilevski @adrianna-chang-shopify

Copy link
Contributor

@adrianna-chang-shopify adrianna-chang-shopify left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple comments but looks good overall!

assert_not_nil record_with_defaults.modified_time
assert_not_nil record_with_defaults.modified_time_without_precision
assert_not_nil record_with_defaults.modified_time_function
if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter, :Mysql2Adapter, :TrilogyAdapter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not used to seeing all of these adapters listed -- is this so that we avoid running the tests against OracleAdapter, etc?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. I have seen recently (can't find that issue/PR) that someone mentioned they use active record tests as part of their adapter tests.

if current_adapter?(:PostgreSQLAdapter) && ActiveRecord::Base.connection.supports_identity_columns?
klass = Class.new(ActiveRecord::Base) do
self.table_name = "postgresql_identity_table"
if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm finding it difficult to follow this test, since we're asserting different things for different adapters 😅 Maybe we could pull the assertions that are adapter-specific out into separate tests, one per adapter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, extracted as separate test cases.

Comment on lines 198 to 200
def return_value_after_insert?(column) # :nodoc:
column.auto_populated?
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we make this the default in AbstractAdapter?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is :nodoc: and the same for all adapters, so I think yes. Did that.


if insert.skip_duplicates?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching this to INSERT IGNORE 👌

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adrianna-chang-shopify @fatkodima @nvasilevski Why is this change desirable? I don't see any discussion of why we want to use INSERT IGNORE over a no-op ON DUPLICATE KEY UPDATE. I haven't tested but I think the behaviour may be different.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

INSERT IGNORE generates a warning and ON DUPLICATE KEY UPPDATE does not.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, so I thought that these are equivalent. Do you mean MariaDB warning?

Copy link
Member Author

@fatkodima fatkodima Nov 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see from the docs what you mean. Thanks for pinging! I will open a PR with the fix.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With RETURNING clause INSERT ON DUPLICATE UPDATE no_op always returns all (even not actually inserted) rows in result set.
INSERT IGNORE returns only the actually inserted rows and in this behaviour it coincides with postgresql adapter.

MariaDB [db]> CREATE TABLE tmp_users (
    ->   id int(11) NOT NULL AUTO_INCREMENT,
    ->   email varchar(255) NOT NULL,
    ->   PRIMARY KEY (id),
    ->   UNIQUE KEY unique_users_email (email)
    -> );
Query OK, 0 rows affected (0,010 sec)

MariaDB [db]> insert ignore tmp_users (email) values ('one@example.com'), ('two@examp.com');
Query OK, 2 rows affected (0,002 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [db]> insert tmp_users (email) values ('one@example.com'), ('two@examp.com') ON DUPLICATE KEY UPDATE id=id returning id, email;
+----+-----------------+
| id | email           |
+----+-----------------+
|  1 | one@example.com |
|  2 | two@examp.com   |
+----+-----------------+
2 rows in set (0,001 sec)

MariaDB [db]> insert ignore tmp_users (email) values ('one@example.com'), ('two@examp.com') returning id, email;
Empty set, 2 warnings (0,001 sec)

After #49890 we won't know which of the rows were inserted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhawthorn , @fatkodima 👀 ☝🏻

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you open a new issue with all of the information describing your problem? Pinging maintainers is not a good way to get a response

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this was addressed already: eecd672

Co-authored-by: Nikolay Kondratyev <nkondratyev@yandex.ru>
@byroot byroot merged commit cb185fc into rails:main Oct 31, 2023
4 checks passed
@fatkodima fatkodima deleted the insert-returning-mariadb branch October 31, 2023 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants