Slide 1

Slide 1 text

PostgreSQLとRuby on Rails

Slide 2

Slide 2 text

Who am I 本多康夫 / Yasuo Honda Ruby on Rails contributor https://contributors.rubyonrails.org/contributors/yasuo-honda/commits Maintainer of Active Record Oracle enhanced adapter https://github.com/rsim/oracle-enhanced Technical support engineer at PingCAP Japan Contact Twitter / GitHub @yahonda Email: yahonda@pingcap.com

Slide 3

Slide 3 text

目的 Ruby on RailsがどのようにPostgreSQLをサポートしているのか知ってもらう

Slide 4

Slide 4 text

Ruby on Rails Ruby言語で書かれたWebアプリケーションフレームワーク GitHub, Shopifyなどで利用されている

Slide 5

Slide 5 text

Active Record Railsに含まれるORM PostgreSQL 9.3以降、MySQL 5.5.8以降、SQLite 3.8以降に対応 新しいバージョンの上限は設定されていない i.e PostgreSQL 14がでたら動作するように変更がされる CIでは postgres:alpine Docker imageにより、最新バージョンでテストされる ある程度データベースごとの独自機能を有効に活用するようになっている(私見)

Slide 6

Slide 6 text

PostgreSQLで有効になっている機能(メソッド名) サポートしているすべてのPostgreSQLで有効 supports_bulk_alter? supports_index_sort_order? supports_partial_index? supports_expression_index? supports_transaction_isolation? supports_foreign_keys? supports_check_constraints?

Slide 7

Slide 7 text

PostgreSQLで有効になっている機能(メソッド名2) サポートしているすべてのPostgreSQLで有効(続) supports_validate_constraints? supports_views? supports_datetime_with_precision? supports_json? supports_comments? supports_savepoints? supports_insert_returning? index_algorithms { concurrently: "CONCURRENTLY" } PostgreSQL 9.5以降でのみ有効 supports_insert_on_conflict? PostgreSQL 11以降でのみ有効 supports_partitioned_indexes?

Slide 8

Slide 8 text

Ruby on RailsのPostgreSQL 14サポート状況 2021年9月30日にPostgreSQL 14がリリースされた https://www.postgresql.org/about/news/postgresql-14-released-2318/ 2021年10月4日頃から、RailsのCIが落ち始める PostgreSQL 14関連の変更によるものが2つ enumの出力順序が変わる libpqでのttyオプションの廃止

Slide 9

Slide 9 text

enumの出力順序が変わる - Fail状況 Failした結果の抜粋 ActiveRecord::Schema.define(version: 0) do ... snip ... # Custom types defined in this database. # Note that some types may not work with other database engines. Be careful if changing database. create_enum "mood", ["happy", "ok", "sad"] end create_enum メソッド第2引数のarray要素の順序が違う assert output.include?('create_enum "mood", ["sad", "ok", "happy"]'), output

Slide 10

Slide 10 text

enumの出力順序が変わる - 修正コード string_agg 関数の中で enumsortorder で明示的に order by するように変更 https://github.com/rails/rails/pull/43371/files query = <<~SQL SELECT type.typname AS name, - string_agg(enum.enumlabel, ',') AS value + string_agg(enum.enumlabel, ',' ORDER BY enum.enumsortorder) AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid)

Slide 11

Slide 11 text

enumの出力順序が変わる - SQL文での再現コード DROP TYPE IF EXISTS mood; DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_type t WHERE t.typname = 'mood' ) THEN CREATE TYPE "mood" AS ENUM ('sad', 'ok', 'happy'); END IF; END $$; SELECT type.typname AS name, string_agg(enum.enumlabel, ',') AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid) GROUP BY type.typname;

Slide 12

Slide 12 text

enumの出力順序が変わる - PostgreSQL 13での結果 : sad,ok,happy activerecord_unittest=# SELECT type.typname AS name, string_agg(enum.enumlabel, ',') AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid) GROUP BY type.typname; name | value ------+-------------- mood | sad,ok,happy (1 row)

Slide 13

Slide 13 text

enumの出力順序が変わる - PostgreSQL 14での結果 : happy,ok,sad activerecord_unittest=# SELECT type.typname AS name, string_agg(enum.enumlabel, ',') AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid) GROUP BY type.typname; name | value ------+-------------- mood | happy,ok,sad (1 row)

Slide 14

Slide 14 text

enumの出力順序が変わる - PostgreSQL 13.4での実行計 画 activerecord_unittest=# explain activerecord_unittest-# SELECT type.typname AS name, string_agg(enum.enumlabel, ',') AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid) GROUP BY type.typname; QUERY PLAN ----------------------------------------------------------------------------------------- GroupAggregate (cost=130.53..148.08 rows=780 width=96) Group Key: type.typname -> Sort (cost=130.53..132.48 rows=780 width=128) Sort Key: type.typname -> Hash Join (cost=73.20..93.06 rows=780 width=128) Hash Cond: (enum.enumtypid = type.oid) -> Seq Scan on pg_enum enum (cost=0.00..17.80 rows=780 width=68) -> Hash (cost=58.09..58.09 rows=1209 width=68) -> Seq Scan on pg_type type (cost=0.00..58.09 rows=1209 width=68) (9 rows)

Slide 15

Slide 15 text

enumの出力順序が変わる - PostgreSQL 14.0での実行計 画 : Sort 処理が消えている activerecord_unittest=# explain activerecord_unittest-# SELECT type.typname AS name, string_agg(enum.enumlabel, ',') AS value FROM pg_enum AS enum JOIN pg_type AS type ON (type.oid = enum.enumtypid) GROUP BY type.typname; QUERY PLAN -------------------------------------------------------------------------------- HashAggregate (cost=75.85..76.82 rows=78 width=96) Group Key: type.typname -> Hash Join (cost=2.75..75.26 rows=78 width=128) Hash Cond: (type.oid = enum.enumtypid) -> Seq Scan on pg_type type (cost=0.00..67.71 rows=1071 width=68) -> Hash (cost=1.78..1.78 rows=78 width=68) -> Seq Scan on pg_enum enum (cost=0.00..1.78 rows=78 width=68) (7 rows)

Slide 16

Slide 16 text

enumの出力順序が変わる - わかっていること,いないこと PostgreSQL 13でも「並び順はデフォルトでは指定されません」と書いてある https://www.postgresql.jp/document/13/html/functions-aggregate.html 集約関数(中略)string_agg、およびxmlagg、そして類似のユーザ定義の集約関数 は、入力値の順序に依存した意味のある別の結果値を生成します。 この並び順はデ フォルトでは指定されませんが、4.2.7に記述されているように、集計呼び出し中 にORDER BY句を書くことで制御可能となります。 PostgreSQL 14 Beta 2(2021年6月24日)の時点で再現することがわかった https://www.postgresql.org/about/news/postgresql-14-beta-2-released-2249/ PostgreSQL 13から14の間のどのcommitによる振る舞いの変更なのかはわからなかった PostgreSQLのコードをgit bisectしてビルドすれば理論上可能のはず 具体的なやり方をご存じの方は教えてください

Slide 17

Slide 17 text

libpqでのttyオプションの廃止 - 修正コード libpqに渡す接続文字列でttyオプションの値を空文字 '' から nil に変更している https://github.com/QueueClassic/queue_classic/pull/334 [ host, # host or percent-encoded socket path url.port || 5432, - nil, '', #opts, tty + nil, nil, #opts, tty url.path.gsub("/",""), # database name url.user, url.password

Slide 18

Slide 18 text

libpqでのttyオプションの廃止 - この変更が有用なわけ(1) 検索したところ、"篠田の虎の巻「PostgreSQL 14 新機能検証結果」"に乗っていそうな ことがわかった https://community.hpe.com/t5/HPE-Blog-Japan/篠田の虎の巻-PostgreSQL-14-GA-新 機能検証結果-公開/ba-p/7151317#.YXgEyZ-RX0p 2.5.13. LIBPQ 接続文字列 接続文字列の authtype および tty は削除されました。SSL 圧縮を行うクライアン ト接続 設定 sslcompression はバックエンドでは無視されます。

Slide 19

Slide 19 text

libpqでのttyオプションの廃止 - この変更が有用なわけ(2) 該当するcommitまで教えていただきました https://twitter.com/nori_shinoda/status/1445278813311561728 「接続文字列の authtype および tty は削除されました。」のcommit https://github.com/postgres/postgres/commit/14d9b37607ad30c3848ea0f2955a7 8436eff1268 2003年(PostgreSQL 7.4)からdeprecatedになったttyオプションが、約18年たって PostgreSQL 14で削除された https://github.com/postgres/postgres/commit/cb7fb3ca958ec8bd5a14e740c067f1d 096af3454

Slide 20

Slide 20 text

Thank you Twitter / GitHub @yahonda Email: yahonda@pingcap.com