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/ext/extconf.rb CHANGED
@@ -1,7 +1,6 @@
1
1
  require 'pp'
2
2
  require 'mkmf'
3
3
 
4
-
5
4
  if ENV['MAINTAINER_MODE']
6
5
  $stderr.puts "Maintainer mode enabled."
7
6
  $CFLAGS <<
@@ -9,18 +8,178 @@ if ENV['MAINTAINER_MODE']
9
8
  ' -ggdb' <<
10
9
  ' -DDEBUG' <<
11
10
  ' -pedantic'
11
+ $LDFLAGS <<
12
+ ' -ggdb'
12
13
  end
13
14
 
14
15
  if pgdir = with_config( 'pg' )
15
16
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
16
17
  end
17
18
 
18
- if enable_config("windows-cross")
19
+ if enable_config("gvl-unlock", true)
20
+ $defs.push( "-DENABLE_GVL_UNLOCK" )
21
+ $stderr.puts "Calling libpq with GVL unlocked"
22
+ else
23
+ $stderr.puts "Calling libpq with GVL locked"
24
+ end
25
+
26
+ if gem_platform=with_config("cross-build")
27
+ gem 'mini_portile2', '~>2.1'
28
+ require 'mini_portile2'
29
+
30
+ OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '3.5.1'
31
+ OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
32
+
33
+ KRB5_VERSION = ENV['KRB5_VERSION'] || '1.21.3'
34
+ KRB5_SOURCE_URI = "http://kerberos.org/dist/krb5/#{KRB5_VERSION[/^(\d+\.\d+)/]}/krb5-#{KRB5_VERSION}.tar.gz"
35
+
36
+ POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '17.5'
37
+ POSTGRESQL_SOURCE_URI = "http://ftp.postgresql.org/pub/source/v#{POSTGRESQL_VERSION}/postgresql-#{POSTGRESQL_VERSION}.tar.bz2"
38
+
39
+ class BuildRecipe < MiniPortile
40
+ def initialize(name, version, files)
41
+ super(name, version)
42
+ self.files = files
43
+ rootdir = File.expand_path('../..', __FILE__)
44
+ self.target = File.join(rootdir, "ports")
45
+ self.patch_files = Dir[File.join(target, "patches", self.name, self.version, "*.patch")].sort
46
+ end
47
+
48
+ def port_path
49
+ "#{target}/#{RUBY_PLATFORM}"
50
+ end
51
+
52
+ def cook_and_activate
53
+ checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{RUBY_PLATFORM}.installed")
54
+ unless File.exist?(checkpoint)
55
+ self.cook
56
+ FileUtils.touch checkpoint
57
+ end
58
+ self.activate
59
+ self
60
+ end
61
+ end
62
+
63
+ openssl_platform = with_config("openssl-platform")
64
+ toolchain = with_config("toolchain")
65
+
66
+ openssl_recipe = BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe|
67
+ class << recipe
68
+ attr_accessor :openssl_platform
69
+ def configure
70
+ envs = []
71
+ envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /mingw|mswin/
72
+ envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /linux|darwin/
73
+ execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", configure_prefix], altlog: "config.log")
74
+ end
75
+ def compile
76
+ execute('compile', "#{make_cmd} build_libs")
77
+ end
78
+ def install
79
+ execute('install', "#{make_cmd} install_dev")
80
+ end
81
+ end
82
+
83
+ recipe.openssl_platform = openssl_platform
84
+ recipe.host = toolchain
85
+ recipe.cook_and_activate
86
+ end
87
+
88
+ if RUBY_PLATFORM =~ /linux|darwin/
89
+ krb5_recipe = BuildRecipe.new("krb5", KRB5_VERSION, [KRB5_SOURCE_URI]).tap do |recipe|
90
+ class << recipe
91
+ def work_path
92
+ File.join(super, "src")
93
+ end
94
+ def configure
95
+ if RUBY_PLATFORM=~/darwin/
96
+ ENV["CC"] = host[/^.*[^\.\d]/] + "-clang"
97
+ ENV["CXX"] = host[/^.*[^\.\d]/] + "-c++"
98
+
99
+ # Manually set the correct values for configure checks that libkrb5 won't be
100
+ # able to perform because we're cross-compiling.
101
+ ENV["krb5_cv_attr_constructor_destructor"] = "yes"
102
+ ENV["ac_cv_func_regcomp"] = "yes"
103
+ ENV["ac_cv_printf_positional"] = "yes"
104
+ end
105
+ super
106
+ end
107
+ end
108
+ # We specify -fcommon to get around duplicate definition errors in recent gcc.
109
+ # See https://github.com/cockroachdb/cockroach/issues/49734
110
+ recipe.configure_options << "CFLAGS=-fcommon#{" -fPIC" if RUBY_PLATFORM =~ /linux/}"
111
+ recipe.configure_options << "LDFLAGS=-framework Kerberos" if RUBY_PLATFORM =~ /darwin/
112
+ recipe.configure_options << "--without-keyutils"
113
+ recipe.configure_options << "--disable-nls"
114
+ recipe.configure_options << "--disable-silent-rules"
115
+ recipe.configure_options << "--without-system-verto"
116
+ recipe.configure_options << "krb5_cv_attr_constructor_destructor=yes"
117
+ recipe.configure_options << "ac_cv_func_regcomp=yes"
118
+ recipe.configure_options << "ac_cv_printf_positional=yes"
119
+ recipe.host = toolchain
120
+ recipe.cook_and_activate
121
+ end
122
+ end
123
+
124
+ # We build a libpq library file which static links OpenSSL and krb5.
125
+ # Our builtin libpq is referenced in different ways depending on the OS:
126
+ # - Window: Add the ports directory at runtime per RubyInstaller::Runtime.add_dll_directory
127
+ # The file is called "libpq.dll"
128
+ # - Linux: Add a rpath to pg_ext.so which references the ports directory.
129
+ # The file is called "libpq-ruby-pg.so.1" to avoid loading of system libpq by accident.
130
+ # - Macos: Add a reference with relative path in pg_ext.so to the ports directory.
131
+ # The file is called "libpq-ruby-pg.1.dylib" to avoid loading of other libpq by accident.
132
+ libpq_orig, libpq_rubypg = case RUBY_PLATFORM
133
+ when /linux/ then ["libpq.so.5", "libpq-ruby-pg.so.1"]
134
+ when /darwin/ then ["libpq.5.dylib", "libpq-ruby-pg.1.dylib"]
135
+ # when /mingw/ then ["libpq.dll", "libpq.dll"] # renaming not needed
136
+ end
137
+
138
+ postgresql_recipe = BuildRecipe.new("postgresql", POSTGRESQL_VERSION, [POSTGRESQL_SOURCE_URI]).tap do |recipe|
139
+ class << recipe
140
+ def configure_defaults
141
+ [
142
+ "--target=#{host}",
143
+ "--host=#{host}",
144
+ '--with-openssl',
145
+ *(RUBY_PLATFORM=~/linux|darwin/ ? ['--with-gssapi'] : []),
146
+ '--without-zlib',
147
+ '--without-icu',
148
+ '--without-readline',
149
+ 'ac_cv_search_gss_store_cred_into=',
150
+ ]
151
+ end
152
+ def compile
153
+ execute 'compile include', "#{make_cmd} -C src/include install"
154
+ execute 'compile interfaces', "#{make_cmd} -C src/interfaces install"
155
+ end
156
+ def install
157
+ end
158
+ end
159
+
160
+ recipe.host = toolchain
161
+ recipe.configure_options << "CFLAGS=#{" -fPIC" if RUBY_PLATFORM =~ /linux|darwin/}"
162
+ recipe.configure_options << "LDFLAGS=-L#{openssl_recipe.path}/lib -L#{openssl_recipe.path}/lib64 -L#{openssl_recipe.path}/lib-arm64 #{"-Wl,-soname,#{libpq_rubypg} -lgssapi_krb5 -lkrb5 -lk5crypto -lkrb5support -ldl" if RUBY_PLATFORM =~ /linux/} #{"-Wl,-install_name,@loader_path/../../ports/#{gem_platform}/lib/#{libpq_rubypg} -lgssapi_krb5 -lkrb5 -lk5crypto -lkrb5support -lresolv -framework Kerberos" if RUBY_PLATFORM =~ /darwin/}"
163
+ recipe.configure_options << "LIBS=-lkrb5 -lcom_err -lk5crypto -lkrb5support -lresolv" if RUBY_PLATFORM =~ /linux/
164
+ recipe.configure_options << "LIBS=-lssl -lwsock32 -lgdi32 -lws2_32 -lcrypt32" if RUBY_PLATFORM =~ /mingw|mswin/
165
+ recipe.configure_options << "CPPFLAGS=-I#{openssl_recipe.path}/include"
166
+ recipe.cook_and_activate
167
+ end
168
+
169
+ # Use our own library name for libpq to avoid loading of system libpq by accident.
170
+ FileUtils.ln_sf File.join(postgresql_recipe.port_path, "lib/#{libpq_orig}"),
171
+ File.join(postgresql_recipe.port_path, "lib/#{libpq_rubypg}")
19
172
  # Avoid dependency to external libgcc.dll on x86-mingw32
20
- $LDFLAGS << " -static-libgcc"
173
+ $LDFLAGS << " -static-libgcc" if RUBY_PLATFORM =~ /mingw|mswin/
174
+ # Avoid: "libpq.so: undefined reference to `dlopen'" in cross-ruby-2.7.8
175
+ $LDFLAGS << " -Wl,--no-as-needed" if RUBY_PLATFORM !~ /aarch64|arm64|darwin/
176
+ # Find libpq in the ports directory coming from lib/3.x
177
+ # It is shared between all compiled ruby versions.
178
+ $LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../ports/#{gem_platform}/lib'" if RUBY_PLATFORM =~ /linux/
21
179
  # Don't use pg_config for cross build, but --with-pg-* path options
22
- dir_config 'pg'
180
+ dir_config('pg', "#{postgresql_recipe.path}/include", "#{postgresql_recipe.path}/lib")
23
181
 
182
+ $defs.push( "-DPG_IS_BINARY_GEM")
24
183
  else
25
184
  # Native build
26
185
 
@@ -30,35 +189,101 @@ else
30
189
 
31
190
  if pgconfig && pgconfig != 'ignore'
32
191
  $stderr.puts "Using config values from %s" % [ pgconfig ]
33
- incdir = `"#{pgconfig}" --includedir`.chomp
34
- libdir = `"#{pgconfig}" --libdir`.chomp
192
+ incdir = IO.popen([pgconfig, "--includedir"], &:read).chomp
193
+ libdir = IO.popen([pgconfig, "--libdir"], &:read).chomp
35
194
  dir_config 'pg', incdir, libdir
36
195
 
37
- # Try to use runtime path linker option, even if RbConfig doesn't know about it.
38
- # The rpath option is usually set implicit by dir_config(), but so far not
39
- # on MacOS-X.
40
- if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
41
- $LDFLAGS << " -Wl,-rpath,#{libdir}"
196
+ # Windows traditionally stores DLLs beside executables, not in libdir
197
+ dlldir = RUBY_PLATFORM=~/mingw|mswin/ ? IO.popen([pgconfig, "--bindir"], &:read).chomp : libdir
198
+
199
+ elsif checking_for "libpq per pkg-config" do
200
+ _cflags, ldflags, _libs = pkg_config("libpq")
201
+ dlldir = ldflags && ldflags[/-L([^ ]+)/] && $1
42
202
  end
203
+
43
204
  else
44
- $stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
45
- " --with-pg-config=/path/to/pg_config"
46
- dir_config 'pg'
205
+ incdir, libdir = dir_config 'pg'
206
+ dlldir = libdir
47
207
  end
208
+
209
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
210
+ # The rpath option is usually set implicit by dir_config(), but so far not
211
+ # on MacOS-X.
212
+ if dlldir && RbConfig::CONFIG["RPATHFLAG"].to_s.empty?
213
+ append_ldflags "-Wl,-rpath,#{dlldir.quote}"
214
+ end
215
+
216
+ if /mswin/ =~ RUBY_PLATFORM
217
+ $libs = append_library($libs, 'ws2_32')
218
+ end
219
+ end
220
+
221
+ $stderr.puts "Using libpq from #{dlldir}"
222
+
223
+ File.write("postgresql_lib_path.rb", <<-EOT)
224
+ module PG
225
+ POSTGRESQL_LIB_PATH = #{dlldir.inspect}
48
226
  end
227
+ EOT
228
+ $INSTALLFILES = {
229
+ "./postgresql_lib_path.rb" => "$(RUBYLIBDIR)/pg/"
230
+ }
49
231
 
50
- if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
232
+ if /solaris/ =~ RUBY_PLATFORM
51
233
  append_cppflags( '-D__EXTENSIONS__' )
52
234
  end
53
235
 
54
- find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
55
- find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
56
- find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
236
+ begin
237
+ find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
238
+ find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
239
+ find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
57
240
 
58
- abort "Can't find the PostgreSQL client library (libpq)" unless
59
- have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
60
- have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
61
- have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
241
+ abort "Can't find the PostgreSQL client library (libpq)" unless
242
+ have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
243
+ have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
244
+ have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
245
+
246
+ rescue SystemExit
247
+ install_text = case RUBY_PLATFORM
248
+ when /linux/
249
+ <<-EOT
250
+ Please install libpq or postgresql client package like so:
251
+ sudo apt install libpq-dev
252
+ sudo yum install postgresql-devel
253
+ sudo zypper in postgresql-devel
254
+ sudo pacman -S postgresql-libs
255
+ EOT
256
+ when /darwin/
257
+ <<-EOT
258
+ Please install libpq or postgresql client package like so:
259
+ brew install libpq
260
+ EOT
261
+ when /mingw/
262
+ <<-EOT
263
+ Please install libpq or postgresql client package like so:
264
+ ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
265
+ EOT
266
+ else
267
+ <<-EOT
268
+ Please install libpq or postgresql client package.
269
+ EOT
270
+ end
271
+
272
+ $stderr.puts <<-EOT
273
+ *****************************************************************************
274
+
275
+ Unable to find PostgreSQL client library.
276
+
277
+ #{install_text}
278
+ or try again with:
279
+ gem install pg -- --with-pg-config=/path/to/pg_config
280
+
281
+ or set library paths manually with:
282
+ gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/
283
+
284
+ EOT
285
+ raise
286
+ end
62
287
 
63
288
  if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
64
289
  # Work around: https://sourceware.org/bugzilla/show_bug.cgi?id=22504
@@ -69,21 +294,22 @@ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
69
294
  end
70
295
  end
71
296
 
72
- # optional headers/functions
73
- have_func 'PQsetSingleRowMode' or
297
+ have_func 'PQencryptPasswordConn', 'libpq-fe.h' or # since PostgreSQL-10
74
298
  abort "Your PostgreSQL is too old. Either install an older version " +
75
- "of this gem or upgrade your database to at least PostgreSQL-9.2."
76
- have_func 'PQconninfo' # since PostgreSQL-9.3
77
- have_func 'PQsslAttribute' # since PostgreSQL-9.5
78
- have_func 'PQresultVerboseErrorMessage' # since PostgreSQL-9.6
79
- have_func 'PQencryptPasswordConn' # since PostgreSQL-10
80
- have_func 'PQresultMemorySize' # since PostgreSQL-12
299
+ "of this gem or upgrade your database to at least PostgreSQL-10."
300
+ # optional headers/functions
301
+ have_func 'PQresultMemorySize', 'libpq-fe.h' # since PostgreSQL-12
302
+ have_func 'PQenterPipelineMode', 'libpq-fe.h' do |src| # since PostgreSQL-14
303
+ # Ensure header files fit as well
304
+ src + " int con(){ return PGRES_PIPELINE_SYNC; }"
305
+ end
306
+ have_func 'PQsetChunkedRowsMode', 'libpq-fe.h' # since PostgreSQL-17
81
307
  have_func 'timegm'
82
- have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
308
+ have_func 'rb_io_wait' # since ruby-3.0
309
+ have_func 'rb_io_descriptor' # since ruby-3.1
83
310
 
84
- # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
85
- have_header 'unistd.h'
86
311
  have_header 'inttypes.h'
312
+ have_header('ruby/fiber/scheduler.h') if RUBY_PLATFORM=~/mingw|mswin/
87
313
 
88
314
  checking_for "C99 variable length arrays" do
89
315
  $defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
data/ext/gvl_wrappers.c CHANGED
@@ -5,13 +5,28 @@
5
5
 
6
6
  #include "pg.h"
7
7
 
8
- #ifndef HAVE_PQENCRYPTPASSWORDCONN
9
- char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm){return NULL;}
8
+
9
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
10
+ PGresult *PQclosePrepared(PGconn *conn, const char *stmtName){return NULL;}
11
+ PGresult *PQclosePortal(PGconn *conn, const char *portalName){return NULL;}
12
+ int PQsendClosePrepared(PGconn *conn, const char *stmtName){return 0;}
13
+ int PQsendClosePortal(PGconn *conn, const char *portalName){return 0;}
14
+ int PQsendPipelineSync(PGconn *conn){return 0;}
15
+ int PQcancelBlocking(PGcancelConn *cancelConn){return 0;}
16
+ int PQcancelStart(PGcancelConn *cancelConn){return 0;}
17
+ PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn){return PGRES_POLLING_FAILED;}
18
+ #endif
19
+ #ifndef HAVE_PQENTERPIPELINEMODE
20
+ int PQpipelineSync(PGconn *conn){return 0;}
10
21
  #endif
11
22
 
23
+ #ifdef ENABLE_GVL_UNLOCK
12
24
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
13
25
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
26
+ #endif
14
27
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
28
+ #ifdef ENABLE_GVL_UNLOCK
15
29
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
16
30
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
31
+ #endif
17
32
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
data/ext/gvl_wrappers.h CHANGED
@@ -17,6 +17,14 @@
17
17
 
18
18
  #include <ruby/thread.h>
19
19
 
20
+ #ifdef RUBY_EXTCONF_H
21
+ # include RUBY_EXTCONF_H
22
+ #endif
23
+
24
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
25
+ typedef struct pg_cancel_conn PGcancelConn;
26
+ #endif
27
+
20
28
  #define DEFINE_PARAM_LIST1(type, name) \
21
29
  name,
22
30
 
@@ -46,6 +54,7 @@
46
54
  return NULL; \
47
55
  }
48
56
 
57
+ #ifdef ENABLE_GVL_UNLOCK
49
58
  #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
50
59
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
51
60
  struct gvl_wrapper_##name##_params params = { \
@@ -54,6 +63,13 @@
54
63
  rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, RUBY_UBF_IO, 0); \
55
64
  when_non_void( return params.retval; ) \
56
65
  }
66
+ #else
67
+ #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
68
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
69
+ when_non_void( return ) \
70
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
71
+ }
72
+ #endif
57
73
 
58
74
  #define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
59
75
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
@@ -66,6 +82,7 @@
66
82
  return NULL; \
67
83
  }
68
84
 
85
+ #ifdef ENABLE_GVL_UNLOCK
69
86
  #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
70
87
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
71
88
  struct gvl_wrapper_##name##_params params = { \
@@ -74,6 +91,13 @@
74
91
  rb_thread_call_with_gvl(gvl_##name##_skeleton, &params); \
75
92
  when_non_void( return params.retval; ) \
76
93
  }
94
+ #else
95
+ #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
96
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
97
+ when_non_void( return ) \
98
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
99
+ }
100
+ #endif
77
101
 
78
102
  #define GVL_TYPE_VOID(string)
79
103
  #define GVL_TYPE_NONVOID(string) string
@@ -95,6 +119,8 @@
95
119
 
96
120
  #define FOR_EACH_PARAM_OF_PQresetPoll(param)
97
121
 
122
+ #define FOR_EACH_PARAM_OF_PQping(param)
123
+
98
124
  #define FOR_EACH_PARAM_OF_PQexec(param) \
99
125
  param(PGconn *, conn)
100
126
 
@@ -127,6 +153,12 @@
127
153
  #define FOR_EACH_PARAM_OF_PQdescribePortal(param) \
128
154
  param(PGconn *, conn)
129
155
 
156
+ #define FOR_EACH_PARAM_OF_PQclosePrepared(param) \
157
+ param(PGconn *, conn)
158
+
159
+ #define FOR_EACH_PARAM_OF_PQclosePortal(param) \
160
+ param(PGconn *, conn)
161
+
130
162
  #define FOR_EACH_PARAM_OF_PQgetResult(param)
131
163
 
132
164
  #define FOR_EACH_PARAM_OF_PQputCopyData(param) \
@@ -174,11 +206,25 @@
174
206
  #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
175
207
  param(PGconn *, conn)
176
208
 
209
+ #define FOR_EACH_PARAM_OF_PQsendClosePrepared(param) \
210
+ param(PGconn *, conn)
211
+
212
+ #define FOR_EACH_PARAM_OF_PQsendClosePortal(param) \
213
+ param(PGconn *, conn)
214
+
215
+ #define FOR_EACH_PARAM_OF_PQpipelineSync(param)
216
+
217
+ #define FOR_EACH_PARAM_OF_PQsendPipelineSync(param)
218
+
177
219
  #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
178
220
  param(PGconn *, conn)
179
221
 
180
222
  #define FOR_EACH_PARAM_OF_PQisBusy(param)
181
223
 
224
+ #define FOR_EACH_PARAM_OF_PQcancelBlocking(param)
225
+ #define FOR_EACH_PARAM_OF_PQcancelStart(param)
226
+ #define FOR_EACH_PARAM_OF_PQcancelPoll(param)
227
+
182
228
  #define FOR_EACH_PARAM_OF_PQencryptPasswordConn(param) \
183
229
  param(PGconn *, conn) \
184
230
  param(const char *, passwd) \
@@ -196,12 +242,15 @@
196
242
  function(PQreset, GVL_TYPE_VOID, void, PGconn *, conn) \
197
243
  function(PQresetStart, GVL_TYPE_NONVOID, int, PGconn *, conn) \
198
244
  function(PQresetPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
245
+ function(PQping, GVL_TYPE_NONVOID, PGPing, const char *, conninfo) \
199
246
  function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
200
247
  function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
201
248
  function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
202
249
  function(PQprepare, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
203
250
  function(PQdescribePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
204
251
  function(PQdescribePortal, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
252
+ function(PQclosePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
253
+ function(PQclosePortal, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
205
254
  function(PQgetResult, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
206
255
  function(PQputCopyData, GVL_TYPE_NONVOID, int, int, nbytes) \
207
256
  function(PQputCopyEnd, GVL_TYPE_NONVOID, int, const char *, errormsg) \
@@ -213,8 +262,15 @@
213
262
  function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
214
263
  function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
215
264
  function(PQsendDescribePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
265
+ function(PQsendClosePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
266
+ function(PQsendClosePortal, GVL_TYPE_NONVOID, int, const char *, portal) \
267
+ function(PQpipelineSync, GVL_TYPE_NONVOID, int, PGconn *, conn) \
268
+ function(PQsendPipelineSync, GVL_TYPE_NONVOID, int, PGconn *, conn) \
216
269
  function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
217
270
  function(PQisBusy, GVL_TYPE_NONVOID, int, PGconn *, conn) \
271
+ function(PQcancelBlocking, GVL_TYPE_NONVOID, int, PGcancelConn *, conn) \
272
+ function(PQcancelStart, GVL_TYPE_NONVOID, int, PGcancelConn *, conn) \
273
+ function(PQcancelPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGcancelConn *, conn) \
218
274
  function(PQencryptPasswordConn, GVL_TYPE_NONVOID, char *, const char *, algorithm) \
219
275
  function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
220
276