Rails 7.2 をちょこっと試す (insert_all returning オプション編 (ただしMariaDBに限る))

## はじめに
Rails 7.2 では、MariaDB で、`insert_all` に `returning` オプションが使えるようになりました。
MySQL では使えないので注意が必要です。
（PostgreSQL では、以前から `returning` オプションが使えます。）
## 環境
- Ruby 3.3.2
- Rails 7.2.0.beta2
- MariaDB 11.4.2
- MySQL 8.4.0

## 準備
Bookモデルを作ります。
```sh
$ bin/rails g model Book title
```

## MySQL での挙動


MySQL では `returning` オプションを使うとエラーになります。
MySQL に接続するように `config/database.yml` を修正して以下を実行します。
```sh
$ bin/rails db:create db:migrate
```

Rails コンソールで `insert_all` を `:returning`実行するとエラーになります。
```ruby
$ bin/rails c
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
(sandbox):1:in `<main>': ActiveRecord::ConnectionAdapters::Mysql2Adapter does not support :returning (ArgumentError)

          raise ArgumentError, "#{connection.class} does not support :returning"
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

ちなみに、`returning` オプションを使わない場合は、 `@rows` が `[]` の `ActiveRecord::Result` が返ります。
```ruby
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}])
  Book Insert (2.7ms)  INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (1, 'Programming Ruby', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) AS `books_values` ON DUPLICATE KEY UPDATE `id`=`books_values`.`id`
=>
#<ActiveRecord::Result:0x0000ffff902bf738
 @column_indexes=nil,
 @column_types={},
 @columns=[],
 @hash_rows=nil,
 @rows=[]>
```

## MariaDB での挙動

MariaDB では、`returning` オプションを使うと、 `ActiveRecord::Result` が返ります。

MariaDB に接続するように `config/database.yml` を修正して以下を実行します。
```sh
$ bin/rails db:create db:migrate
```

Rails コンソールで `insert_all` を `:returning`オプションつきで、実行すると、 `ActiveRecord::Result` が返ります。
```ruby
sandbox(dev)> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
  Book Insert (1.0ms)  INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (1, 'Programming Ruby', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) ON DUPLICATE KEY UPDATE `id`=`id` RETURNING `id`,`title`
    =>
#<ActiveRecord::Result:0x0000ffff843cf468
 @column_indexes=nil,
 @column_types={},
 @columns=["id", "title"],
 @hash_rows=nil,
 @rows=[[1, "Programming Ruby"]]>
```

ちなみに `returning` オプションを省略した場合は、 `id` の情報だけの `ActiveRecord::Result` が返ります。

```ruby
sandbox(dev)> Book.insert_all([{id: 2, title: 'Rails development'}])
  Book Insert (1.1ms)  INSERT INTO `books` (`id`,`title`,`created_at`,`updated_at`) VALUES (2, 'Rails development', CURRENT_TIMESTAMP(6), CURRENT_TIMESTAMP(6)) ON DUPLICATE KEY UPDATE `id`=`id` RETURNING `id`
    =>
#<ActiveRecord::Result:0x0000ffff84254340
 @column_indexes=nil,
     @column_types={},
     @columns=["id"],
     @hash_rows=nil,
     @rows=[[2]]>
```

## Rails 7.1 での挙動

Rails 7.1 では、`returning` オプションを使うとエラーになります。

```ruby
irb(main):001> Book.insert_all([{id: 1, title: 'Programming Ruby'}], returning: %w[id title])
(irb):1:in `<main>': ActiveRecord::ConnectionAdapters::Mysql2Adapter does not support :returning (ArgumentError)

          raise ArgumentError, "#{connection.class} does not support :returning"
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```

## まとめ

- Rails 7.2 では、MariaDB で `insert_all` に `returning` オプションが使えるようになりました。
- MySQL では使えないので注意が必要です。

## 参考
- https://github.com/rails/rails/pull/49840