pg 1.2.3 → 1.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +986 -0
  4. data/Gemfile +23 -0
  5. data/README-Windows.rdoc +1 -1
  6. data/README.ja.md +300 -0
  7. data/README.md +327 -0
  8. data/Rakefile +123 -144
  9. data/certs/ged.pem +24 -0
  10. data/certs/kanis@comcard.de.pem +20 -0
  11. data/certs/larskanis-2022.pem +26 -0
  12. data/certs/larskanis-2023.pem +24 -0
  13. data/certs/larskanis-2024.pem +24 -0
  14. data/ext/errorcodes.def +16 -5
  15. data/ext/errorcodes.rb +0 -0
  16. data/ext/errorcodes.txt +5 -5
  17. data/ext/extconf.rb +259 -33
  18. data/ext/gvl_wrappers.c +17 -2
  19. data/ext/gvl_wrappers.h +56 -0
  20. data/ext/pg.c +89 -63
  21. data/ext/pg.h +31 -8
  22. data/ext/pg_binary_decoder.c +232 -1
  23. data/ext/pg_binary_encoder.c +428 -1
  24. data/ext/pg_cancel_connection.c +360 -0
  25. data/ext/pg_coder.c +148 -36
  26. data/ext/pg_connection.c +1365 -817
  27. data/ext/pg_copy_coder.c +360 -38
  28. data/ext/pg_errors.c +1 -1
  29. data/ext/pg_record_coder.c +56 -25
  30. data/ext/pg_result.c +187 -76
  31. data/ext/pg_text_decoder.c +32 -11
  32. data/ext/pg_text_encoder.c +65 -33
  33. data/ext/pg_tuple.c +84 -61
  34. data/ext/pg_type_map.c +44 -10
  35. data/ext/pg_type_map_all_strings.c +17 -3
  36. data/ext/pg_type_map_by_class.c +54 -27
  37. data/ext/pg_type_map_by_column.c +74 -31
  38. data/ext/pg_type_map_by_mri_type.c +48 -19
  39. data/ext/pg_type_map_by_oid.c +61 -27
  40. data/ext/pg_type_map_in_ruby.c +55 -21
  41. data/ext/pg_util.c +2 -2
  42. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  43. data/lib/pg/basic_type_map_for_queries.rb +206 -0
  44. data/lib/pg/basic_type_map_for_results.rb +104 -0
  45. data/lib/pg/basic_type_registry.rb +311 -0
  46. data/lib/pg/binary_decoder/date.rb +9 -0
  47. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  48. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  49. data/lib/pg/cancel_connection.rb +53 -0
  50. data/lib/pg/coder.rb +18 -14
  51. data/lib/pg/connection.rb +894 -91
  52. data/lib/pg/exceptions.rb +20 -1
  53. data/lib/pg/text_decoder/date.rb +21 -0
  54. data/lib/pg/text_decoder/inet.rb +9 -0
  55. data/lib/pg/text_decoder/json.rb +17 -0
  56. data/lib/pg/text_decoder/numeric.rb +9 -0
  57. data/lib/pg/text_decoder/timestamp.rb +30 -0
  58. data/lib/pg/text_encoder/date.rb +13 -0
  59. data/lib/pg/text_encoder/inet.rb +31 -0
  60. data/lib/pg/text_encoder/json.rb +17 -0
  61. data/lib/pg/text_encoder/numeric.rb +9 -0
  62. data/lib/pg/text_encoder/timestamp.rb +24 -0
  63. data/lib/pg/version.rb +4 -0
  64. data/lib/pg.rb +109 -39
  65. data/misc/openssl-pg-segfault.rb +31 -0
  66. data/misc/postgres/History.txt +9 -0
  67. data/misc/postgres/Manifest.txt +5 -0
  68. data/misc/postgres/README.txt +21 -0
  69. data/misc/postgres/Rakefile +21 -0
  70. data/misc/postgres/lib/postgres.rb +16 -0
  71. data/misc/ruby-pg/History.txt +9 -0
  72. data/misc/ruby-pg/Manifest.txt +5 -0
  73. data/misc/ruby-pg/README.txt +21 -0
  74. data/misc/ruby-pg/Rakefile +21 -0
  75. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  76. data/misc/yugabyte/Dockerfile +9 -0
  77. data/misc/yugabyte/docker-compose.yml +28 -0
  78. data/misc/yugabyte/pg-test.rb +45 -0
  79. data/pg.gemspec +38 -0
  80. data/ports/patches/krb5/1.21.3/0001-Allow-static-linking-krb5-library.patch +30 -0
  81. data/ports/patches/openssl/3.5.1/0001-aarch64-mingw.patch +21 -0
  82. data/ports/patches/postgresql/17.5/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
  83. data/ports/patches/postgresql/17.5/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
  84. data/rakelib/pg_gem_helper.rb +64 -0
  85. data/rakelib/task_extension.rb +46 -0
  86. data/sample/array_insert.rb +20 -0
  87. data/sample/async_api.rb +102 -0
  88. data/sample/async_copyto.rb +39 -0
  89. data/sample/async_mixed.rb +56 -0
  90. data/sample/check_conn.rb +21 -0
  91. data/sample/copydata.rb +71 -0
  92. data/sample/copyfrom.rb +81 -0
  93. data/sample/copyto.rb +19 -0
  94. data/sample/cursor.rb +21 -0
  95. data/sample/disk_usage_report.rb +177 -0
  96. data/sample/issue-119.rb +94 -0
  97. data/sample/losample.rb +69 -0
  98. data/sample/minimal-testcase.rb +17 -0
  99. data/sample/notify_wait.rb +72 -0
  100. data/sample/pg_statistics.rb +285 -0
  101. data/sample/replication_monitor.rb +222 -0
  102. data/sample/test_binary_values.rb +33 -0
  103. data/sample/wal_shipper.rb +434 -0
  104. data/sample/warehouse_partitions.rb +311 -0
  105. data.tar.gz.sig +0 -0
  106. metadata +139 -213
  107. metadata.gz.sig +0 -0
  108. data/.gemtest +0 -0
  109. data/ChangeLog +0 -0
  110. data/History.rdoc +0 -578
  111. data/Manifest.txt +0 -73
  112. data/README.ja.rdoc +0 -13
  113. data/README.rdoc +0 -213
  114. data/Rakefile.cross +0 -299
  115. data/lib/pg/basic_type_mapping.rb +0 -522
  116. data/lib/pg/binary_decoder.rb +0 -23
  117. data/lib/pg/constants.rb +0 -12
  118. data/lib/pg/text_decoder.rb +0 -46
  119. data/lib/pg/text_encoder.rb +0 -59
  120. data/spec/data/expected_trace.out +0 -26
  121. data/spec/data/random_binary_data +0 -0
  122. data/spec/helpers.rb +0 -380
  123. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  124. data/spec/pg/connection_spec.rb +0 -1949
  125. data/spec/pg/connection_sync_spec.rb +0 -41
  126. data/spec/pg/result_spec.rb +0 -681
  127. data/spec/pg/tuple_spec.rb +0 -333
  128. data/spec/pg/type_map_by_class_spec.rb +0 -138
  129. data/spec/pg/type_map_by_column_spec.rb +0 -226
  130. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  131. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  132. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  133. data/spec/pg/type_map_spec.rb +0 -22
  134. data/spec/pg/type_spec.rb +0 -1123
  135. data/spec/pg_spec.rb +0 -50
data/Gemfile ADDED
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ # Specify your gem's runtime dependencies in pg.gemspec
4
+ gemspec
5
+
6
+ source "https://rubygems.org/"
7
+
8
+ group :development do
9
+ gem "rdoc", "~> 6.4"
10
+ gem "mini_portile2", "~> 2.1"
11
+ end
12
+
13
+ group :test do
14
+ gem "bundler", ">= 1.16", "< 3.0"
15
+ gem "rake-compiler", "~> 1.0"
16
+ gem "rake-compiler-dock", "~> 1.9.1"
17
+ gem "rspec", "~> 3.5"
18
+ # "bigdecimal" is a gem on ruby-3.4+ and it's optional for ruby-pg.
19
+ # Specs should succeed without it, but 4 examples are then excluded.
20
+ # With bigdecimal commented out here, corresponding tests are omitted on ruby-3.4+ but are executed on ruby < 3.4.
21
+ # That way we can check both situations in CI.
22
+ # gem "bigdecimal", "~> 3.0"
23
+ end
data/README-Windows.rdoc CHANGED
@@ -41,7 +41,7 @@ sure it is started. A native Docker installation is best on Linux.
41
41
 
42
42
  Then run:
43
43
 
44
- rake gem:windows
44
+ rake gem:native
45
45
 
46
46
  This will download a docker image suited for building windows gems, and it
47
47
  will download and build OpenSSL and PostgreSQL. Finally the gem is built
data/README.ja.md ADDED
@@ -0,0 +1,300 @@
1
+ # pg
2
+
3
+ * ホーム :: https://github.com/ged/ruby-pg
4
+ * ドキュメント :: http://deveiate.org/code/pg (英語)、 https://deveiate.org/code/pg/README_ja_md.html (日本語)
5
+ * 変更履歴 :: link:/CHANGELOG.md
6
+
7
+ [![https://gitter.im/ged/ruby-pg
8
+ でチャットに参加](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ged/ruby-pg?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
9
+
10
+
11
+ ## 説明
12
+
13
+ Pgは[PostgreSQL
14
+ RDBMS](http://www.postgresql.org/)へのRubyのインターフェースです。[PostgreSQL
15
+ 10以降](http://www.postgresql.org/support/versioning/)で動作します。
16
+
17
+ 簡単な使用例は次の通りです。
18
+ ```ruby
19
+ #!/usr/bin/env ruby
20
+
21
+ require 'pg'
22
+
23
+ # データベースへの現在の接続を表に出力します
24
+ conn = PG.connect( dbname: 'sales' )
25
+ conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
26
+ puts " PID | User | Query"
27
+ result.each do |row|
28
+ puts " %7d | %-16s | %s " %
29
+ row.values_at('pid', 'usename', 'query')
30
+ end
31
+ end
32
+ ```
33
+
34
+ ## ビルド状況
35
+
36
+ [![Github
37
+ Actionsのビルド状況](https://github.com/ged/ruby-pg/actions/workflows/source-gem.yml/badge.svg?branch=master)](https://github.com/ged/ruby-pg/actions/workflows/source-gem.yml)
38
+ [![バイナリgem](https://github.com/ged/ruby-pg/actions/workflows/binary-gems.yml/badge.svg?branch=master)](https://github.com/ged/ruby-pg/actions/workflows/binary-gems.yml)
39
+ [![Appveyorのビルド状況](https://ci.appveyor.com/api/projects/status/gjx5axouf3b1wicp?svg=true)](https://ci.appveyor.com/project/ged/ruby-pg-9j8l3)
40
+
41
+
42
+ ## 要件
43
+
44
+ * Ruby 2.7かそれより新しいバージョン
45
+ * PostgreSQL 10.xかそれ以降のバージョン(ヘッダー付属のもの、例えば-devの名前のパッケージ)。
46
+
47
+ それより前のバージョンのRubyやPostgreSQLでも通常は同様に動作しますが、定期的なテストはされていません。
48
+
49
+
50
+ ## バージョン管理
51
+
52
+ [セマンティックバージョニング](http://semver.org/)の原則にしたがってgemをタグ付けしてリリースしています。
53
+
54
+ この方針の結果として、2つの数字を指定する[悲観的バージョン制約](http://guides.rubygems.org/patterns/#pessimistic-version-constraint)を使ってこのgemへの依存関係を指定することができます(またそうすべきです)。
55
+
56
+ 例えば次の通りです。
57
+
58
+ ```ruby
59
+ spec.add_dependency 'pg', '~> 1.0'
60
+ ```
61
+
62
+ ## インストール方法
63
+
64
+ RubyGemsを経由してインストールするには以下とします。
65
+
66
+ gem install pg
67
+
68
+ Postgresと一緒にインストールされた'pg_config'プログラムへのパスを指定する必要があるかもしれません。
69
+
70
+ gem install pg -- --with-pg-config=<path to pg_config>
71
+
72
+ Bundlerを介してインストールした場合は次のようにコンパイルのためのヒントを与えられます。
73
+
74
+ bundle config build.pg --with-pg-config=<path to pg_config>
75
+
76
+ MacOS Xへインストールする詳しい情報については README-OS_X.rdoc を、Windows用のビルドやインストールの説明については
77
+ README-Windows.rdoc を参照してください。
78
+
79
+ 詰まったときやただ何か喋りたいときのために[Google+グループ](http://goo.gl/TFy1U)と[メーリングリスト](http://groups.google.com/group/ruby-pg)もあります。
80
+
81
+ 署名されたgemとしてインストールしたい場合は、リポジトリの[`certs`ディレクトリ](https://github.com/ged/ruby-pg/tree/master/certs)にgemの署名をする公開証明書があります。
82
+
83
+
84
+ ## 型変換
85
+
86
+ Pgでは任意でRubyと素のCコードにある結果の値やクエリ引数の型変換ができます。
87
+ こうすることでデータベースとのデータの往来を加速させられます。
88
+ なぜなら文字列のアロケーションが減り、(比較的遅い)Rubyのコードでの変換部分が省かれるからです。
89
+
90
+ とても基本的な型変換は次のようにできます。
91
+ ```ruby
92
+ conn.type_map_for_results = PG::BasicTypeMapForResults.new conn
93
+ # ……これは結果の値の対応付けに作用します。
94
+ conn.exec("select 1, now(), '{2,3}'::int[]").values
95
+ # => [[1, 2014-09-21 20:51:56 +0200, [2, 3]]]
96
+
97
+ conn.type_map_for_queries = PG::BasicTypeMapForQueries.new conn
98
+ # ……そしてこれは引数値の対応付けのためのものです。
99
+ conn.exec_params("SELECT $1::text, $2::text, $3::text", [1, 1.23, [2,3]]).values
100
+ # => [["1", "1.2300000000000000E+00", "{2,3}"]]
101
+ ```
102
+
103
+ しかしPgの型変換はかなり調整が効きます。2層に分かれているのがその理由です。
104
+
105
+ ### エンコーダーとデコーダー (ext/pg_*coder.c, lib/pg/*coder.rb)
106
+
107
+ こちらはより低層で、DBMSへ転送するためにRubyのオブジェクトを変換するエンコーディングクラスと、取得してきたデータをRubyのオブジェクトに変換し戻すデコーディングクラスが含まれています。
108
+ クラスはそれぞれの形式によって名前空間 PG::TextEncoder, PG::TextDecoder, PG::BinaryEncoder, そして
109
+ PG::BinaryDecoder に分かれています。
110
+
111
+ エンコーダーないしデコーダーオブジェクトにOIDデータ型や形式コード(テキストないしバイナリ)や任意で名前を割り当てることができます。
112
+ 要素のエンコーダーないしデコーダーを割り当てることによって複合型を構築することもできます。
113
+ PG::Coder オブジェクトは PG::TypeMap をセットアップしたり、その代わりに単一の値と文字列表現とを相互に変換したりするのに使えます。
114
+
115
+ ruby-pgでは以下のPostgreSQLカラム型に対応しています(TE = Text Encoder、TD = Text Decoder、BE =
116
+ Binary Encoder、BD = Binary Decoder)。
117
+
118
+ * Integer:
119
+ [TE](rdoc-ref:PG::TextEncoder::Integer)、[TD](rdoc-ref:PG::TextDecoder::Integer)、[BD](rdoc-ref:PG::BinaryDecoder::Integer)
120
+ 💡
121
+ リンクがないでしょうか。[こちら](https://deveiate.org/code/pg/README_ja_md.html#label-E5-9E-8B-E5-A4-89-E6-8F-9B)を代わりに見てください
122
+ 💡
123
+ * BE:
124
+ [Int2](rdoc-ref:PG::BinaryEncoder::Int2)、[Int4](rdoc-ref:PG::BinaryEncoder::Int4)、[Int8](rdoc-ref:PG::BinaryEncoder::Int8)
125
+ * Float:
126
+ [TE](rdoc-ref:PG::TextEncoder::Float)、[TD](rdoc-ref:PG::TextDecoder::Float)、[BD](rdoc-ref:PG::BinaryDecoder::Float)
127
+ * BE: [Float4](rdoc-ref:PG::BinaryEncoder::Float4),
128
+ [Float8](rdoc-ref:PG::BinaryEncoder::Float8)
129
+ * Numeric:
130
+ [TE](rdoc-ref:PG::TextEncoder::Numeric)、[TD](rdoc-ref:PG::TextDecoder::Numeric)
131
+ * Boolean:
132
+ [TE](rdoc-ref:PG::TextEncoder::Boolean)、[TD](rdoc-ref:PG::TextDecoder::Boolean)、[BE](rdoc-ref:PG::BinaryEncoder::Boolean)、[BD](rdoc-ref:PG::BinaryDecoder::Boolean)
133
+ * String:
134
+ [TE](rdoc-ref:PG::TextEncoder::String)、[TD](rdoc-ref:PG::TextDecoder::String)、[BE](rdoc-ref:PG::BinaryEncoder::String)、[BD](rdoc-ref:PG::BinaryDecoder::String)
135
+ * Bytea:
136
+ [TE](rdoc-ref:PG::TextEncoder::Bytea)、[TD](rdoc-ref:PG::TextDecoder::Bytea)、[BE](rdoc-ref:PG::BinaryEncoder::Bytea)、[BD](rdoc-ref:PG::BinaryDecoder::Bytea)
137
+ * Base64:
138
+ [TE](rdoc-ref:PG::TextEncoder::ToBase64)、[TD](rdoc-ref:PG::TextDecoder::FromBase64)、[BE](rdoc-ref:PG::BinaryEncoder::FromBase64)、[BD](rdoc-ref:PG::BinaryDecoder::ToBase64)
139
+ * Timestamp:
140
+ * TE:
141
+ [現地時間](rdoc-ref:PG::TextEncoder::TimestampWithoutTimeZone)、[UTC](rdoc-ref:PG::TextEncoder::TimestampUtc)、[タイムゾーン付き](rdoc-ref:PG::TextEncoder::TimestampWithTimeZone)
142
+ * TD:
143
+ [現地時間](rdoc-ref:PG::TextDecoder::TimestampLocal)、[UTC](rdoc-ref:PG::TextDecoder::TimestampUtc)、[UTCから現地時間へ](rdoc-ref:PG::TextDecoder::TimestampUtcToLocal)
144
+ * BE:
145
+ [現地時間](rdoc-ref:PG::BinaryEncoder::TimestampLocal)、[UTC](rdoc-ref:PG::BinaryEncoder::TimestampUtc)
146
+ * BD:
147
+ [現地時間](rdoc-ref:PG::BinaryDecoder::TimestampLocal)、[UTC](rdoc-ref:PG::BinaryDecoder::TimestampUtc)、[UTCから現地時間へ](rdoc-ref:PG::BinaryDecoder::TimestampUtcToLocal)
148
+ * 日付:[TE](rdoc-ref:PG::TextEncoder::Date)、[TD](rdoc-ref:PG::TextDecoder::Date)、[BE](rdoc-ref:PG::BinaryEncoder::Date)、[BD](rdoc-ref:PG::BinaryDecoder::Date)
149
+ * JSONとJSONB:
150
+ [TE](rdoc-ref:PG::TextEncoder::JSON)、[TD](rdoc-ref:PG::TextDecoder::JSON)
151
+ * Inet:
152
+ [TE](rdoc-ref:PG::TextEncoder::Inet)、[TD](rdoc-ref:PG::TextDecoder::Inet)
153
+ * Array:
154
+ [TE](rdoc-ref:PG::TextEncoder::Array)、[TD](rdoc-ref:PG::TextDecoder::Array)
155
+ * 複合型(「行」や「レコード」などとも言います):[TE](rdoc-ref:PG::TextEncoder::Record)、[TD](rdoc-ref:PG::TextDecoder::Record)
156
+
157
+ カラム型として使われていませんが、以下のテキスト形式とバイナリ形式もエンコードできます。
158
+
159
+ * COPYの入出力データ:[TE](rdoc-ref:PG::TextEncoder::CopyRow)、[TD](rdoc-ref:PG::TextDecoder::CopyRow),
160
+ [BE](rdoc-ref:PG::BinaryEncoder::CopyRow),
161
+ [BD](rdoc-ref:PG::BinaryDecoder::CopyRow)
162
+ * SQL文字列に挿入するリテラル:[TE](rdoc-ref:PG::TextEncoder::QuotedLiteral)
163
+ * SQLの識別子:
164
+ [TE](rdoc-ref:PG::TextEncoder::Identifier)、[TD](rdoc-ref:PG::TextDecoder::Identifier)
165
+
166
+ ### PG::TypeMap とその派生 (ext/pg_type_map*.c, lib/pg/type_map*.rb)
167
+
168
+ TypeMapはエンコーダーまたはデコーダーのどちらによってどの値を変換するかを定義します。
169
+ 様々な型の対応付け戦略があるので、このクラスにはいくつかの派生が実装されています。
170
+ 型変換の特有の需要に合わせてそれらの派生から選んで調整を加えることができます。
171
+ 既定の型の対応付けは PG::TypeMapAllStrings です。
172
+
173
+ 型の対応付けは、結果の集合それぞれに対し、接続毎ないしクエリ毎に割り当てることができます。
174
+ 型の対応付けはCOPYの入出力データストリーミングでも使うことができます。
175
+ PG::Connection#copy_data を参照してください。
176
+
177
+ 以下の基底となる型の対応付けが使えます。
178
+
179
+ * PG::TypeMapAllStrings - 全ての値と文字列について相互にエンコードとデコードを行います(既定)
180
+ * PG::TypeMapByClass - 送信する値のクラスに基づいてエンコーダーを選択します
181
+ * PG::TypeMapByColumn - カラムの順番によってエンコーダーとデコーダーを選択します
182
+ * PG::TypeMapByOid - PostgreSQLのOIDデータ型によってデコーダーを選択します
183
+ * PG::TypeMapInRuby - Rubyで独自の型の対応付けを定義します
184
+
185
+ 以下の型の対応付けは PG::BasicTypeRegistry 由来の型の対応付けが入った状態になっています。
186
+
187
+ * PG::BasicTypeMapForResults - PG::TypeMapByOid
188
+ によくあるPostgreSQLカラム型用にデコーダーが入った状態になっています
189
+ * PG::BasicTypeMapBasedOnResult - PG::TypeMapByOid
190
+ によくあるPostgreSQLカラム型用のエンコーダーが入った状態になっています
191
+ * PG::BasicTypeMapForQueries - PG::TypeMapByClass
192
+ によくあるRubyの値クラス用にエンコーダーが入った状態になっています
193
+
194
+
195
+ ## スレッド対応
196
+
197
+ PGには個々のスレッドが別々の PG::Connection オブジェクトを同時に使えるという点でスレッド安全性があります。
198
+ しかし1つ以上のスレッドから同時にPgのオブジェクトにアクセスすると安全ではありません。
199
+ そのため必ず、毎回新しいスレッドを作るときに新しいデータベースサーバー接続を開くか、スレッド安全性のある方法で接続を管理するActiveRecordのようなラッパーライブラリを使うようにしてください。
200
+
201
+ 以下のようなメッセージが標準エラー出力に表示された場合、恐らく複数のスレッドが1つの接続を使っています。
202
+
203
+ message type 0x31 arrived from server while idle
204
+ message type 0x32 arrived from server while idle
205
+ message type 0x54 arrived from server while idle
206
+ message type 0x43 arrived from server while idle
207
+ message type 0x5a arrived from server while idle
208
+
209
+
210
+ ## Fiber IOスケジューラー対応
211
+
212
+ pg-1.3.0以降で、PgはRuby-3.0で導入された`Fiber.scheduler`に完全に対応しています。
213
+ Windowsでは、`Fiber.scheduler`対応はRuby-3.1以降で使えます。
214
+ `Fiber.scheduler`が走らせているスレッドに登録されている場合、起こりうる全てのブロッキングIO操作はそのスケジューラーを経由します。
215
+ 同期的であったりブロックしたりするメソッド呼び出しについてもpgが内部的に非同期のlibpqインターフェースを使っているのはそれが理由です。
216
+ またlibpqの組み込み関数に代えてRubyのDNS解決を使っています。
217
+
218
+ 内部的にPgは常にlibpqのノンブロッキング接続モードを使います。
219
+ それからブロッキングモードで走っているように振舞いますが、もし`Fiber.scheduler`が登録されていれば全てのブロッキングIOはそのスケジューラーを通じてRubyで制御されます。
220
+ `PG::Connection.setnonblocking(true)`が呼ばれたらノンブロッキング状態が有効になったままになりますが、それ以降のブロッキング状態の制御が無効になるので、呼び出しているプログラムはブロッキング状態を自力で制御しなければなりません。
221
+
222
+ この規則の1つの例外には、`PG::Connection#lo_create`や外部ライブラリを使う認証メソッド(GSSAPI認証など)のような、大きめのオブジェクト用のメソッドがあります。これらは`Fiber.scheduler`と互換性がないため、ブロッキング状態は登録されたIOスケジューラに渡されません。つまり操作は適切に実行されますが、IO待ち状態に別のIOを扱うFiberから使用を切り替えてくることができなくなります。
223
+
224
+
225
+ ## Ractor対応
226
+
227
+ pg-1.5.0以降で、PgはRuby-3.0で導入されたRactorと完全な互換性があります。
228
+ 型エンコーダーないしデコーダー、及び型の対応付けが`Ractor.make_shareable`により凍結されている場合、これらをractor間で共有できます。
229
+ また凍結された PG::Result と PG::Tuple オブジェクトも共有できます。
230
+ 少なくとも全ての凍結されたオブジェクト(ただし PG::Connection
231
+ を除く)はPostgreSQLサーバーとのやり取りをしたり取得されたデータを読むのに使えます。
232
+
233
+ PG::Connection は共有できません。個々の接続を確立するために、それぞれのRactor内で作られなければなりません。
234
+
235
+
236
+ ## 貢献
237
+
238
+ バグを報告したり機能を提案したりGitでソースをチェックアウトしたりするには[プロジェクトページをご確認ください](https://github.com/ged/ruby-pg)。
239
+
240
+ ソースをチェックアウトしたあとは全ての依存関係をインストールします。
241
+
242
+ $ bundle install
243
+
244
+ 拡張ファイル、パッケージファイル、テストデータベースを一掃するには、このコマンドを走らせてください。PostgreSQLのバージョンも切り替わります。
245
+
246
+ $ rake clean
247
+
248
+ 拡張をコンパイルするには次のようにします。
249
+
250
+ $ rake compile
251
+
252
+ `pg_config --bindir`が指すPostgreSQLのバージョンでテストやスペックを走らせるには次のようにします。
253
+
254
+ $ rake test
255
+
256
+ あるいは特定のPostgreSQLのバージョンで、ファイル中の行番号を使って特定のテストを走らせるには次のようにします。
257
+
258
+ $ PATH=/usr/lib/postgresql/14/bin:$PATH rspec -Ilib -fd spec/pg/connection_spec.rb:455
259
+
260
+ APIドキュメントを生成するには次のようにします。
261
+
262
+ $ rake docs
263
+
264
+ 必ず全てのバグと新機能についてテストを使って検証してください。
265
+
266
+ 現在のメンテナはMichael Granger <ged@FaerieMUD.org>とLars Kanis
267
+ <lars@greiz-reinsdorf.de>です。
268
+
269
+
270
+ ## 著作権
271
+
272
+ Copyright (c) 1997-2022 by the authors.
273
+
274
+ * Jeff Davis <ruby-pg@j-davis.com>
275
+ * Guy Decoux (ts) <decoux@moulon.inra.fr>
276
+ * Michael Granger <ged@FaerieMUD.org>
277
+ * Lars Kanis <lars@greiz-reinsdorf.de>
278
+ * Dave Lee
279
+ * Eiji Matsumoto <usagi@ruby.club.or.jp>
280
+ * Yukihiro Matsumoto <matz@ruby-lang.org>
281
+ * Noboru Saitou <noborus@netlab.jp>
282
+
283
+ You may redistribute this software under the same terms as Ruby itself; see
284
+ https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the
285
+ source for details.
286
+ (参考訳:このソフトウェアはRuby自体と同じ条件の元で再配布することができます。詳細については
287
+ https://www.ruby-lang.org/en/about/license.txt やソース中のBSDLファイルを参照してください)
288
+
289
+ Portions of the code are from the PostgreSQL project, and are distributed "
290
+ "under the terms of the PostgreSQL license, included in the file POSTGRES.
291
+ (参考訳:コードの一部はPostgreSQLプロジェクトから来ており、PostgreSQLの使用許諾の条件の元で配布されます。ファイルPOSTGRESに含まれています)
292
+
293
+ Portions copyright LAIKA, Inc.
294
+
295
+
296
+ ## 謝辞
297
+
298
+ 長年にわたって貢献してくださった方々については Contributors.rdoc を参照してください。
299
+
300
+ ruby-listとruby-devメーリングリストの方々に感謝します。またPostgreSQLを開発された方々へも謝意を表します。
data/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # pg
2
+
3
+ * home :: https://github.com/ged/ruby-pg
4
+ * docs :: http://deveiate.org/code/pg (English) ,
5
+ https://deveiate.org/code/pg/README_ja_md.html (Japanese)
6
+ * clog :: link:/CHANGELOG.md
7
+
8
+ [![Join the chat at https://gitter.im/ged/ruby-pg](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/ged/ruby-pg?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
9
+
10
+
11
+ ## Description
12
+
13
+ Pg is the Ruby interface to the [PostgreSQL RDBMS](http://www.postgresql.org/).
14
+ It works with [PostgreSQL 10 and later](http://www.postgresql.org/support/versioning/).
15
+
16
+ A small example usage:
17
+ ```ruby
18
+ #!/usr/bin/env ruby
19
+
20
+ require 'pg'
21
+
22
+ # Output a table of current connections to the DB
23
+ conn = PG.connect( dbname: 'sales' )
24
+ conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
25
+ puts " PID | User | Query"
26
+ result.each do |row|
27
+ puts " %7d | %-16s | %s " %
28
+ row.values_at('pid', 'usename', 'query')
29
+ end
30
+ end
31
+ ```
32
+
33
+ ## Build Status
34
+
35
+ [![Build Status Github Actions](https://github.com/ged/ruby-pg/actions/workflows/source-gem.yml/badge.svg?branch=master)](https://github.com/ged/ruby-pg/actions/workflows/source-gem.yml)
36
+ [![Binary gems](https://github.com/ged/ruby-pg/actions/workflows/binary-gems.yml/badge.svg?branch=master)](https://github.com/ged/ruby-pg/actions/workflows/binary-gems.yml)
37
+ [![Build Status Appveyor](https://ci.appveyor.com/api/projects/status/gjx5axouf3b1wicp?svg=true)](https://ci.appveyor.com/project/ged/ruby-pg-9j8l3)
38
+
39
+
40
+ ## Requirements
41
+
42
+ * Ruby 2.7 or newer
43
+ * PostgreSQL 10.x or later
44
+ * When installing the source gem: libpq with headers, -dev packages, etc.
45
+
46
+
47
+ ## How To Install
48
+
49
+ Install via RubyGems:
50
+
51
+ gem install pg
52
+
53
+ This installs the binary gem, specific to the running platform by default.
54
+
55
+ ### Binary gem
56
+
57
+ The binary gems don't depend on the libpq package on the running system.
58
+ They have libpq builtin.
59
+
60
+ The gems for platform `x86_64-linux` and `aarch64-linux` run on Alpine Linux, but require the package `gcompat` there as long as we don't provide a native gem for platform `x86_64-linux-musl`. Install this package like so:
61
+
62
+ apk add gcompat
63
+
64
+ There is one use case the binary gems don't support: Retrieval of connection [options from LDAP](https://www.postgresql.org/docs/current/libpq-ldap.html). To support this `libldap` would be necessary, but it has a lot of dependencies. It doesn't seem to be a widely used feature and that it's worth to support it. If it's necessary, the source gem can be forced.
65
+
66
+ ### Source gem
67
+
68
+ The source gem can be forced by:
69
+
70
+ gem install pg --platform ruby
71
+
72
+ You may need to specify the path to the 'pg_config' program installed with
73
+ Postgres:
74
+
75
+ gem install pg -- --with-pg-config=<path to pg_config>
76
+
77
+ If you're installing via Bundler, you can provide compile hints like so:
78
+
79
+ bundle config build.pg --with-pg-config=<path to pg_config>
80
+
81
+ ### Bundler
82
+
83
+ To make sure, the necessary platforms and the source gem are fetched by bundler, they can be added like so
84
+
85
+ ```
86
+ bundle lock --add-platform x86_64-linux
87
+ bundle lock --add-platform arm64-darwin
88
+ bundle lock --add-platform x64-mingw-ucrt
89
+ bundle lock --add-platform ruby
90
+ bundle package --all-platforms
91
+ ```
92
+
93
+ A re-run of `bundle package` is also necessary after `bundle update`, in order to retrieve the new specific gems of all platforms.
94
+
95
+ If the binary gems don't work for some reason, it's easy to force the usage of the source gem in the Gemfile:
96
+
97
+ ```
98
+ gem "pg", force_ruby_platform: true
99
+ ```
100
+
101
+ ### More
102
+
103
+ See README-OS_X.rdoc for more information about installing under MacOS X, and
104
+ README-Windows.rdoc for Windows build/installation instructions.
105
+
106
+ There's also [a Google+ group](http://goo.gl/TFy1U) and a
107
+ [mailing list](http://groups.google.com/group/ruby-pg) if you get stuck, or just
108
+ want to chat about something.
109
+
110
+ If you want to install as a signed gem, the public certs of the gem signers
111
+ can be found in [the `certs` directory](https://github.com/ged/ruby-pg/tree/master/certs)
112
+ of the repository.
113
+
114
+
115
+ ## Versioning
116
+
117
+ We tag and release gems according to the [Semantic Versioning](http://semver.org/) principle.
118
+
119
+ As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/#pessimistic-version-constraint) with two digits of precision.
120
+
121
+ For example:
122
+
123
+ ```ruby
124
+ spec.add_dependency 'pg', '~> 1.0'
125
+ ```
126
+
127
+
128
+ ## Type Casts
129
+
130
+ Pg can optionally type cast result values and query parameters in Ruby or
131
+ native C code. This can speed up data transfers to and from the database,
132
+ because String allocations are reduced and conversions in (slower) Ruby code
133
+ can be omitted.
134
+
135
+ Very basic type casting can be enabled by:
136
+ ```ruby
137
+ conn.type_map_for_results = PG::BasicTypeMapForResults.new conn
138
+ # ... this works for result value mapping:
139
+ conn.exec("select 1, now(), '{2,3}'::int[]").values
140
+ # => [[1, 2014-09-21 20:51:56 +0200, [2, 3]]]
141
+
142
+ conn.type_map_for_queries = PG::BasicTypeMapForQueries.new conn
143
+ # ... and this for param value mapping:
144
+ conn.exec_params("SELECT $1::text, $2::text, $3::text", [1, 1.23, [2,3]]).values
145
+ # => [["1", "1.2300000000000000E+00", "{2,3}"]]
146
+ ```
147
+
148
+ But Pg's type casting is highly customizable. That's why it's divided into
149
+ 2 layers:
150
+
151
+ ### Encoders / Decoders (ext/pg_*coder.c, lib/pg/*coder.rb)
152
+
153
+ This is the lower layer, containing encoding classes that convert Ruby
154
+ objects for transmission to the DBMS and decoding classes to convert
155
+ received data back to Ruby objects. The classes are namespaced according
156
+ to their format and direction in PG::TextEncoder, PG::TextDecoder,
157
+ PG::BinaryEncoder and PG::BinaryDecoder.
158
+
159
+ It is possible to assign a type OID, format code (text or binary) and
160
+ optionally a name to an encoder or decoder object. It's also possible
161
+ to build composite types by assigning an element encoder/decoder.
162
+ PG::Coder objects can be used to set up a PG::TypeMap or alternatively
163
+ to convert single values to/from their string representation.
164
+
165
+ The following PostgreSQL column types are supported by ruby-pg (TE = Text Encoder, TD = Text Decoder, BE = Binary Encoder, BD = Binary Decoder):
166
+
167
+ * Integer: [TE](rdoc-ref:PG::TextEncoder::Integer), [TD](rdoc-ref:PG::TextDecoder::Integer), [BD](rdoc-ref:PG::BinaryDecoder::Integer) 💡 No links? Switch to [here](https://deveiate.org/code/pg/README_md.html#label-Type+Casts) 💡
168
+ * BE: [Int2](rdoc-ref:PG::BinaryEncoder::Int2), [Int4](rdoc-ref:PG::BinaryEncoder::Int4), [Int8](rdoc-ref:PG::BinaryEncoder::Int8)
169
+ * Float: [TE](rdoc-ref:PG::TextEncoder::Float), [TD](rdoc-ref:PG::TextDecoder::Float), [BD](rdoc-ref:PG::BinaryDecoder::Float)
170
+ * BE: [Float4](rdoc-ref:PG::BinaryEncoder::Float4), [Float8](rdoc-ref:PG::BinaryEncoder::Float8)
171
+ * Numeric: [TE](rdoc-ref:PG::TextEncoder::Numeric), [TD](rdoc-ref:PG::TextDecoder::Numeric)
172
+ * Boolean: [TE](rdoc-ref:PG::TextEncoder::Boolean), [TD](rdoc-ref:PG::TextDecoder::Boolean), [BE](rdoc-ref:PG::BinaryEncoder::Boolean), [BD](rdoc-ref:PG::BinaryDecoder::Boolean)
173
+ * String: [TE](rdoc-ref:PG::TextEncoder::String), [TD](rdoc-ref:PG::TextDecoder::String), [BE](rdoc-ref:PG::BinaryEncoder::String), [BD](rdoc-ref:PG::BinaryDecoder::String)
174
+ * Bytea: [TE](rdoc-ref:PG::TextEncoder::Bytea), [TD](rdoc-ref:PG::TextDecoder::Bytea), [BE](rdoc-ref:PG::BinaryEncoder::Bytea), [BD](rdoc-ref:PG::BinaryDecoder::Bytea)
175
+ * Base64: [TE](rdoc-ref:PG::TextEncoder::ToBase64), [TD](rdoc-ref:PG::TextDecoder::FromBase64), [BE](rdoc-ref:PG::BinaryEncoder::FromBase64), [BD](rdoc-ref:PG::BinaryDecoder::ToBase64)
176
+ * Timestamp:
177
+ * TE: [local](rdoc-ref:PG::TextEncoder::TimestampWithoutTimeZone), [UTC](rdoc-ref:PG::TextEncoder::TimestampUtc), [with-TZ](rdoc-ref:PG::TextEncoder::TimestampWithTimeZone)
178
+ * TD: [local](rdoc-ref:PG::TextDecoder::TimestampLocal), [UTC](rdoc-ref:PG::TextDecoder::TimestampUtc), [UTC-to-local](rdoc-ref:PG::TextDecoder::TimestampUtcToLocal)
179
+ * BE: [local](rdoc-ref:PG::BinaryEncoder::TimestampLocal), [UTC](rdoc-ref:PG::BinaryEncoder::TimestampUtc)
180
+ * BD: [local](rdoc-ref:PG::BinaryDecoder::TimestampLocal), [UTC](rdoc-ref:PG::BinaryDecoder::TimestampUtc), [UTC-to-local](rdoc-ref:PG::BinaryDecoder::TimestampUtcToLocal)
181
+ * Date: [TE](rdoc-ref:PG::TextEncoder::Date), [TD](rdoc-ref:PG::TextDecoder::Date), [BE](rdoc-ref:PG::BinaryEncoder::Date), [BD](rdoc-ref:PG::BinaryDecoder::Date)
182
+ * JSON and JSONB: [TE](rdoc-ref:PG::TextEncoder::JSON), [TD](rdoc-ref:PG::TextDecoder::JSON)
183
+ * Inet: [TE](rdoc-ref:PG::TextEncoder::Inet), [TD](rdoc-ref:PG::TextDecoder::Inet)
184
+ * Array: [TE](rdoc-ref:PG::TextEncoder::Array), [TD](rdoc-ref:PG::TextDecoder::Array), [BE](rdoc-ref:PG::BinaryEncoder::Array), [BD](rdoc-ref:PG::BinaryDecoder::Array)
185
+ * Composite Type (also called "Row" or "Record"): [TE](rdoc-ref:PG::TextEncoder::Record), [TD](rdoc-ref:PG::TextDecoder::Record)
186
+
187
+ The following text and binary formats can also be encoded although they are not used as column type:
188
+
189
+ * COPY input and output data: [TE](rdoc-ref:PG::TextEncoder::CopyRow), [TD](rdoc-ref:PG::TextDecoder::CopyRow), [BE](rdoc-ref:PG::BinaryEncoder::CopyRow), [BD](rdoc-ref:PG::BinaryDecoder::CopyRow)
190
+ * Literal for insertion into SQL string: [TE](rdoc-ref:PG::TextEncoder::QuotedLiteral)
191
+ * SQL-Identifier: [TE](rdoc-ref:PG::TextEncoder::Identifier), [TD](rdoc-ref:PG::TextDecoder::Identifier)
192
+
193
+ ### PG::TypeMap and derivations (ext/pg_type_map*.c, lib/pg/type_map*.rb)
194
+
195
+ A TypeMap defines which value will be converted by which encoder/decoder.
196
+ There are different type map strategies, implemented by several derivations
197
+ of this class. They can be chosen and configured according to the particular
198
+ needs for type casting. The default type map is PG::TypeMapAllStrings.
199
+
200
+ A type map can be assigned per connection or per query respectively per
201
+ result set. Type maps can also be used for COPY in and out data streaming.
202
+ See PG::Connection#copy_data .
203
+
204
+ The following base type maps are available:
205
+
206
+ * PG::TypeMapAllStrings - encodes and decodes all values to and from strings (default)
207
+ * PG::TypeMapByClass - selects encoder based on the class of the value to be sent
208
+ * PG::TypeMapByColumn - selects encoder and decoder by column order
209
+ * PG::TypeMapByOid - selects decoder by PostgreSQL type OID
210
+ * PG::TypeMapInRuby - define a custom type map in ruby
211
+
212
+ The following type maps are prefilled with type mappings from the PG::BasicTypeRegistry :
213
+
214
+ * PG::BasicTypeMapForResults - a PG::TypeMapByOid prefilled with decoders for common PostgreSQL column types
215
+ * PG::BasicTypeMapBasedOnResult - a PG::TypeMapByOid prefilled with encoders for common PostgreSQL column types
216
+ * PG::BasicTypeMapForQueries - a PG::TypeMapByClass prefilled with encoders for common Ruby value classes
217
+
218
+ Several type maps can be chained by setting PG::TypeMap::DefaultTypeMappable#default_type_map .
219
+
220
+ ## Thread support
221
+
222
+ PG is thread safe in such a way that different threads can use different PG::Connection objects concurrently.
223
+ However it is not safe to access any Pg objects simultaneously from more than one thread.
224
+ So make sure to open a new database server connection for every new thread or use a wrapper library like ActiveRecord that manages connections in a thread safe way.
225
+
226
+ If messages like the following are printed to stderr, you're probably using one connection from several threads:
227
+
228
+ message type 0x31 arrived from server while idle
229
+ message type 0x32 arrived from server while idle
230
+ message type 0x54 arrived from server while idle
231
+ message type 0x43 arrived from server while idle
232
+ message type 0x5a arrived from server while idle
233
+
234
+
235
+ ## Fiber IO scheduler support
236
+
237
+ Pg is fully compatible with `Fiber.scheduler` introduced in Ruby-3.0 since pg-1.3.0.
238
+ On Windows support for `Fiber.scheduler` is available on Ruby-3.1 or newer.
239
+ All possibly blocking IO operations are routed through the `Fiber.scheduler` if one is registered for the running thread.
240
+ That is why pg internally uses the asynchronous libpq interface even for synchronous/blocking method calls.
241
+ It also uses Ruby's DNS resolution instead of libpq's builtin functions.
242
+
243
+ Internally Pg always uses the nonblocking connection mode of libpq.
244
+ It then behaves like running in blocking mode but ensures, that all blocking IO is handled in Ruby through a possibly registered `Fiber.scheduler`.
245
+ When `PG::Connection.setnonblocking(true)` is called then the nonblocking state stays enabled, but the additional handling of blocking states is disabled, so that the calling program has to handle blocking states on its own.
246
+
247
+ An exception to this rule are the methods for large objects like `PG::Connection#lo_create` and authentication methods using external libraries (like GSSAPI authentication).
248
+ They are not compatible with `Fiber.scheduler`, so that blocking states are not passed to the registered IO scheduler.
249
+ That means the operation will work properly, but IO waiting states can not be used to switch to another Fiber doing IO.
250
+
251
+
252
+ ## Ractor support
253
+
254
+ Pg is fully compatible with Ractor introduced in Ruby-3.0 since pg-1.5.0.
255
+ All type en/decoders and type maps are shareable between ractors if they are made frozen by `Ractor.make_shareable`.
256
+ Also frozen PG::Result and PG::Tuple objects can be shared.
257
+ All frozen objects (except PG::Connection) can still be used to do communication with the PostgreSQL server or to read retrieved data.
258
+
259
+ PG::Connection is not shareable and must be created within each Ractor to establish a dedicated connection.
260
+
261
+
262
+ ## Contributing
263
+
264
+ To report bugs, suggest features, or check out the source with Git,
265
+ [check out the project page](https://github.com/ged/ruby-pg).
266
+
267
+ After checking out the source, install all dependencies:
268
+
269
+ $ bundle install
270
+
271
+ Cleanup extension files, packaging files, test databases.
272
+ Run this to change between PostgreSQL versions:
273
+
274
+ $ rake clean
275
+
276
+ Compile extension:
277
+
278
+ $ rake compile
279
+
280
+ Run tests/specs on the PostgreSQL version that `pg_config --bindir` points to:
281
+
282
+ $ rake test
283
+
284
+ Or run a specific test per file and line number on a specific PostgreSQL version:
285
+
286
+ $ PATH=/usr/lib/postgresql/14/bin:$PATH rspec -Ilib -fd spec/pg/connection_spec.rb:455
287
+
288
+ Generate the API documentation:
289
+
290
+ $ rake docs
291
+
292
+ Make sure, that all bugs and new features are verified by tests.
293
+
294
+ The current maintainers are Michael Granger <ged@FaerieMUD.org> and
295
+ Lars Kanis <lars@greiz-reinsdorf.de>.
296
+
297
+
298
+ ## Copying
299
+
300
+ Copyright (c) 1997-2022 by the authors.
301
+
302
+ * Jeff Davis <ruby-pg@j-davis.com>
303
+ * Guy Decoux (ts) <decoux@moulon.inra.fr>
304
+ * Michael Granger <ged@FaerieMUD.org>
305
+ * Lars Kanis <lars@greiz-reinsdorf.de>
306
+ * Dave Lee
307
+ * Eiji Matsumoto <usagi@ruby.club.or.jp>
308
+ * Yukihiro Matsumoto <matz@ruby-lang.org>
309
+ * Noboru Saitou <noborus@netlab.jp>
310
+
311
+ You may redistribute this software under the same terms as Ruby itself; see
312
+ https://www.ruby-lang.org/en/about/license.txt or the BSDL file in the source
313
+ for details.
314
+
315
+ Portions of the code are from the PostgreSQL project, and are distributed
316
+ under the terms of the PostgreSQL license, included in the file POSTGRES.
317
+
318
+ Portions copyright LAIKA, Inc.
319
+
320
+
321
+ ## Acknowledgments
322
+
323
+ See Contributors.rdoc for the many additional fine people that have contributed
324
+ to this library over the years.
325
+
326
+ We are thankful to the people at the ruby-list and ruby-dev mailing lists.
327
+ And to the people who developed PostgreSQL.