Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PostgreSQLとRuby on Rails

Yasuo Honda
November 12, 2021

PostgreSQLとRuby on Rails

Lightning Talk at PostgreSQL Conference Japan 2021

Yasuo Honda

November 12, 2021
Tweet

More Decks by Yasuo Honda

Other Decks in Technology

Transcript

  1. 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: [email protected]
  2. Active Record Railsに含まれるORM PostgreSQL 9.3以降、MySQL 5.5.8以降、SQLite 3.8以降に対応 新しいバージョンの上限は設定されていない i.e PostgreSQL

    14がでたら動作するように変更がされる CIでは postgres:alpine Docker imageにより、最新バージョンでテストされる ある程度データベースごとの独自機能を有効に活用するようになっている(私見)
  3. 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
  4. 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)
  5. 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;
  6. 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)
  7. 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)
  8. 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)
  9. 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)
  10. 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してビルドすれば理論上可能のはず 具体的なやり方をご存じの方は教えてください
  11. 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
  12. 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