pg 1.6.1 → 1.6.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c220f1cc5cfd8e07690949fcf30a96abd8f710bc64f0c358eb6452288966a5b4
4
- data.tar.gz: cd5f28d3098e2537e04dc218c8809b83308cb541e6b17891220559d33e2ada82
3
+ metadata.gz: b98dcd23695bd37aca4e9769e5b55a26ab53b7de01e4b44ff22d1849df08088a
4
+ data.tar.gz: d9610b8ca74c772db98aff8ff661fa29ea44d8917e0ef48f1e89f9cdfd3158b3
5
5
  SHA512:
6
- metadata.gz: f5de3fb30c6da95937d6c8913c9e172a348fa376edc6f06cc9333669c908a25cb2af85853aafbdc6839407f6b4aea93ca97e3b5b53f7182732664ecd6cd81e33
7
- data.tar.gz: 00f5c6e8c359e81bf7c9145b7322583e511d440f681d32192430d9ce96772f1d71f8abce35e12ccf126d96a552205e799efee2533c54a84c623fa0aeee5c1c3c
6
+ metadata.gz: 531c1c61fdb41ea77a8e8e657a536f5734fecc117f7b3a93c04707b7f16a034a841859944e097e75db12ea630ff2679ed90054e0132b96f23ee92c5807d8c07f
7
+ data.tar.gz: 7d7d8d8c0ff76687d63912d41cf4dea890eb63bf361378b9da075ad1f8ccda9b34353e0de0f462bff5cae2740ee17988c3aef417c92d9b38d3a1b635e6ed19f5
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## v1.6.3 [2025-12-29] Lars Kanis <lars@greiz-reinsdorf.de>
2
+
3
+ Added:
4
+ - Add binary gems for ruby-4.0, now providing ruby-3.0 to 4.0. #682
5
+ - Improve documentation of PG::Result and README. #676
6
+ - Update errorcodes to PostgreSQL-18.
7
+ - Use `rb_hash_new_capa` on Ruby-3.2+ . #674
8
+ - Deny any server communication on a frozen PG::Connection . #677
9
+ - Fix possible race condition in PG::Result in Ractor context. #674
10
+
11
+ Removed:
12
+ - Drop binary gem support for platform `x86-mingw32`. #682
13
+ - Drop binary gems for ruby-2.7.
14
+
15
+
16
+ ## v1.6.2 [2025-09-02] Lars Kanis <lars@greiz-reinsdorf.de>
17
+
18
+ - Remove several absolute paths from native binaries which pointed to build directories. [#668](https://github.com/ged/ruby-pg/pull/668)
19
+ - Fix bad fallback path to `pg_service.conf`. [#666](https://github.com/ged/ruby-pg/pull/666)
20
+ - Use `rbpg_` prefix for `base64_*` functions to avoid name clashes with functions provided by other libraries like Heimdal on Macos. [#667](https://github.com/ged/ruby-pg/pull/667)
21
+ - Raise a more descriptive error message in case of `pg_ext` LoadError. [#664](https://github.com/ged/ruby-pg/pull/664)
22
+ - Freeze some constants to make them available in a Ractor context. [#660](https://github.com/ged/ruby-pg/pull/660)
23
+ - Several documentation improvements.
24
+ - Update native binary gems to OpenSSL-3.5.2, krb5-1.22.1 and PostgreSQL-17.6.
25
+
26
+
1
27
  ## v1.6.1 [2025-08-03] Lars Kanis <lars@greiz-reinsdorf.de>
2
28
 
3
29
  - Add binary gems for platforms `aarch64-linux-musl` and `x86_64-linux-musl` without the need to install package `gcompat`. [#657](https://github.com/ged/ruby-pg/pull/657).
data/Gemfile CHANGED
@@ -1,7 +1,7 @@
1
1
  # -*- ruby -*-
2
2
 
3
- # Specify your gem's runtime dependencies in pg.gemspec
4
- gemspec
3
+ # No pg gem, since "bundle package" fails on bundler-2.7+, if the extension isn't built
4
+ # gemspec
5
5
 
6
6
  source "https://rubygems.org/"
7
7
 
@@ -11,9 +11,9 @@ group :development do
11
11
  end
12
12
 
13
13
  group :test do
14
- gem "bundler", ">= 1.16", "< 3.0"
14
+ gem "bundler", ">= 1.16", "< 5.0"
15
15
  gem "rake-compiler", "~> 1.0"
16
- gem "rake-compiler-dock", "~> 1.9.1"
16
+ gem "rake-compiler-dock", "~> 1.11.0" #, git: "https://github.com/rake-compiler/rake-compiler-dock"
17
17
  gem "rspec", "~> 3.5"
18
18
  # "bigdecimal" is a gem on ruby-3.4+ and it's optional for ruby-pg.
19
19
  # Specs should succeed without it, but 4 examples are then excluded.
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # pg
2
2
 
3
3
  * home :: https://github.com/ged/ruby-pg
4
- * docs :: http://deveiate.org/code/pg (English) ,
4
+ * docs :: http://deveiate.org/code/pg/README_md.html (English) ,
5
5
  https://deveiate.org/code/pg/README_ja_md.html (Japanese)
6
6
  * clog :: link:/CHANGELOG.md
7
7
 
@@ -30,6 +30,9 @@ A small example usage:
30
30
  end
31
31
  ```
32
32
 
33
+ See the PG::Connection class for query methods and the PG::Result class for information on working with the results of a query.
34
+
35
+
33
36
  ## Build Status
34
37
 
35
38
  [![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)
@@ -57,9 +60,7 @@ This installs the binary gem, specific to the running platform by default.
57
60
  The binary gems don't depend on the libpq package on the running system.
58
61
  They have libpq builtin.
59
62
 
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
+ The gems for platform `x86_64-linux` and `aarch64-linux` run on Alpine Linux, but require the package `gcompat`, while the native gems for platform `*-linux-musl` work without that dependency.
63
64
 
64
65
  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
 
@@ -67,6 +68,7 @@ There is one use case the binary gems don't support: Retrieval of connection [op
67
68
 
68
69
  The source gem can be forced by:
69
70
 
71
+ gem uninstall pg --all
70
72
  gem install pg --platform ruby
71
73
 
72
74
  You may need to specify the path to the 'pg_config' program installed with
@@ -148,7 +150,7 @@ Very basic type casting can be enabled by:
148
150
  But Pg's type casting is highly customizable. That's why it's divided into
149
151
  2 layers:
150
152
 
151
- ### Encoders / Decoders (ext/pg_*coder.c, lib/pg/*coder.rb)
153
+ ### Encoders / Decoders (ext/pg_\*coder.c, lib/pg/\*coder.rb)
152
154
 
153
155
  This is the lower layer, containing encoding classes that convert Ruby
154
156
  objects for transmission to the DBMS and decoding classes to convert
@@ -190,9 +192,9 @@ The following text and binary formats can also be encoded although they are not
190
192
  * Literal for insertion into SQL string: [TE](rdoc-ref:PG::TextEncoder::QuotedLiteral)
191
193
  * SQL-Identifier: [TE](rdoc-ref:PG::TextEncoder::Identifier), [TD](rdoc-ref:PG::TextDecoder::Identifier)
192
194
 
193
- ### PG::TypeMap and derivations (ext/pg_type_map*.c, lib/pg/type_map*.rb)
195
+ ### TypeMap and derivations (ext/pg_type_map\*.c, lib/pg/type_map\*.rb)
194
196
 
195
- A TypeMap defines which value will be converted by which encoder/decoder.
197
+ A PG::TypeMap defines which value will be converted by which encoder/decoder.
196
198
  There are different type map strategies, implemented by several derivations
197
199
  of this class. They can be chosen and configured according to the particular
198
200
  needs for type casting. The default type map is PG::TypeMapAllStrings.
@@ -219,8 +221,8 @@ Several type maps can be chained by setting PG::TypeMap::DefaultTypeMappable#def
219
221
 
220
222
  ## Thread support
221
223
 
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
+ PG is thread safe in such a way that different threads or fibers can use different PG::Connection objects concurrently.
225
+ However it is not safe to access any PG object simultaneously from more than one thread or fiber unless the object is frozen.
224
226
  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
227
 
226
228
  If messages like the following are printed to stderr, you're probably using one connection from several threads:
data/Rakefile CHANGED
@@ -47,7 +47,6 @@ CrossLibrary = Struct.new :platform, :openssl_config, :toolchain
47
47
  CrossLibraries = [
48
48
  ['aarch64-mingw-ucrt', 'mingwarm64', 'aarch64-w64-mingw32'],
49
49
  ['x64-mingw-ucrt', 'mingw64', 'x86_64-w64-mingw32'],
50
- ['x86-mingw32', 'mingw', 'i686-w64-mingw32'],
51
50
  ['x64-mingw32', 'mingw64', 'x86_64-w64-mingw32'],
52
51
  ['x86_64-linux', 'linux-x86_64', 'x86_64-linux-gnu'],
53
52
  ['x86_64-linux-musl', 'linux-x86_64', 'x86_64-unknown-linux-musl'],
@@ -74,7 +73,7 @@ Rake::ExtensionTask.new do |ext|
74
73
  # Activate current cross compiled platform only.
75
74
  # This is to work around the issue that `linux` platform is selected in `linux-musl` image.
76
75
  ext.cross_platform = CrossLibraries.map(&:platform).select do |pl|
77
- m = ENV["RCD_IMAGE"]&.match(/:(?<ruby_ver>[\d\.]+)-mri-(?<platform>[-\w]+)$/)
76
+ m = ENV["RCD_IMAGE"]&.match(/:(?<ruby_ver>[\w\.]+)-mri-(?<platform>[-\w]+)$/)
78
77
  m && m[:platform] == pl
79
78
  end
80
79
 
@@ -94,7 +93,7 @@ Rake::ExtensionTask.new do |ext|
94
93
  spec.files << "ports/#{spec.platform.to_s}/lib/libpq-ruby-pg.1.dylib" if spec.platform.to_s =~ /darwin/
95
94
  spec.files << "ports/#{spec.platform.to_s}/lib/libpq.dll" if spec.platform.to_s =~ /mingw|mswin/
96
95
 
97
- # Binary gems don't postgresql header+lib files
96
+ # Binary gems don't need postgresql header+lib files
98
97
  spec.metadata.delete("msys2_mingw_dependencies")
99
98
  end
100
99
  end
@@ -106,6 +105,7 @@ task 'gem:native:prepare' do
106
105
  # Copy gem signing key and certs to be accessible from the docker container
107
106
  mkdir_p 'build/gem'
108
107
  sh "cp ~/.gem/gem-*.pem build/gem/ || true"
108
+ sh "bundle config set cache_all false"
109
109
  sh "bundle package"
110
110
  begin
111
111
  OpenSSL::PKey.read(File.read(File.expand_path("~/.gem/gem-private_key.pem")), ENV["GEM_PRIVATE_KEY_PASSPHRASE"] || "")
@@ -115,19 +115,6 @@ task 'gem:native:prepare' do
115
115
  end
116
116
  end
117
117
 
118
- task 'install_darwin_mig', [:arch] do |t, args|
119
- sh <<~EOT
120
- rm -rf bootstrap_cmds &&
121
- git clone --branch=cross_platform https://github.com/markmentovai/bootstrap_cmds &&
122
- cd bootstrap_cmds &&
123
- autoreconf --install &&
124
- sh configure &&
125
- make &&
126
- sed -E -i 's/^cppflags=(.*)/cppflags=(\\1 "-D#{args[:arch]}" "-I\\/opt\\/osxcross\\/target\\/SDK\\/MacOSX11.1.sdk\\/usr\\/include")/' migcom.tproj/mig.sh &&
127
- sudo make install
128
- EOT
129
- end
130
-
131
118
  CrossLibraries.each do |xlib|
132
119
  platform = xlib.platform
133
120
  desc "Build fat binary gem for platform #{platform}"
@@ -139,9 +126,7 @@ CrossLibraries.each do |xlib|
139
126
  sudo apt-get update && sudo apt-get install -y bison flex &&
140
127
  (cp build/gem/gem-*.pem ~/.gem/ || true) &&
141
128
  bundle install --local &&
142
- #{ "rake install_darwin_mig[__arm64__]" if platform =~ /arm64-darwin/ }
143
- #{ "rake install_darwin_mig[__x86_64__]" if platform =~ /x86_64-darwin/ }
144
- rake native:#{platform} pkg/#{$gem_spec.full_name}-#{platform}.gem MAKEOPTS=-j`nproc` RUBY_CC_VERSION=#{RakeCompilerDock.ruby_cc_version("~>2.7", "~>3.0")}
129
+ rake native:#{platform} pkg/#{$gem_spec.full_name}-#{platform}.gem MAKEFLAGS="-j`nproc` V=1" RUBY_CC_VERSION=#{RakeCompilerDock.ruby_cc_version("~>4.0", "~>3.0")}
145
130
  EOT
146
131
  end
147
132
  desc "Build the native binary gems"
@@ -172,7 +157,8 @@ end
172
157
 
173
158
  desc "Update list of server error codes"
174
159
  task :update_error_codes do
175
- URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/REL_17_0"
160
+ # URL_ERRORCODES_TXT = "https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/REL_18_0"
161
+ URL_ERRORCODES_TXT = "https://raw.githubusercontent.com/postgres/postgres/refs/tags/REL_18_0/src/backend/utils/errcodes.txt"
176
162
 
177
163
  ERRORCODES_TXT = "ext/errorcodes.txt"
178
164
  sh "wget #{URL_ERRORCODES_TXT.inspect} -O #{ERRORCODES_TXT.inspect} || curl #{URL_ERRORCODES_TXT.inspect} -o #{ERRORCODES_TXT.inspect}"
data/ext/errorcodes.def CHANGED
@@ -87,6 +87,11 @@
87
87
  VALUE klass = define_error_class( "StackedDiagnosticsAccessedWithoutActiveHandler", "0Z" );
88
88
  register_error_class( "0Z002", klass );
89
89
  }
90
+ {
91
+ VALUE klass = define_error_class( "InvalidArgumentForXquery", NULL );
92
+ register_error_class( "10608", klass );
93
+ register_error_class( "10", klass );
94
+ }
90
95
  {
91
96
  VALUE klass = define_error_class( "CaseNotFound", NULL );
92
97
  register_error_class( "20000", klass );
@@ -889,6 +894,10 @@
889
894
  VALUE klass = define_error_class( "DuplicateFile", "58" );
890
895
  register_error_class( "58P02", klass );
891
896
  }
897
+ {
898
+ VALUE klass = define_error_class( "FileNameTooLong", "58" );
899
+ register_error_class( "58P03", klass );
900
+ }
892
901
  {
893
902
  VALUE klass = define_error_class( "ConfigFileError", NULL );
894
903
  register_error_class( "F0000", klass );
data/ext/errorcodes.rb CHANGED
@@ -28,7 +28,7 @@ EOCODE
28
28
  sqlstate, ews, errcode_macro_name = $1, $2, $3
29
29
  next unless ews=='E'
30
30
 
31
- is_sqlclass = sqlstate[2..-1] == '000'
31
+ is_sqlclass = sqlstate[2..-1] == '000' || sqlstate == '10608'
32
32
  class_code = sqlstate[0,2]
33
33
  baseclass_code = is_sqlclass ? 'NULL' : class_code.inspect
34
34
  class_name = camelize(errcode_macro_name.sub('ERRCODE_', '').downcase)
data/ext/errorcodes.txt CHANGED
@@ -2,7 +2,7 @@
2
2
  # errcodes.txt
3
3
  # PostgreSQL error codes
4
4
  #
5
- # Copyright (c) 2003-2024, PostgreSQL Global Development Group
5
+ # Copyright (c) 2003-2025, PostgreSQL Global Development Group
6
6
  #
7
7
  # This list serves as the basis for generating source files containing error
8
8
  # codes. It is kept in a common format to make sure all these source files have
@@ -141,6 +141,12 @@ Section: Class 0Z - Diagnostics Exception
141
141
  0Z000 E ERRCODE_DIAGNOSTICS_EXCEPTION diagnostics_exception
142
142
  0Z002 E ERRCODE_STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER stacked_diagnostics_accessed_without_active_handler
143
143
 
144
+ Section: Class 10 - XQuery Error
145
+
146
+ # recent SQL versions define quite a few codes in this class, but for now
147
+ # we are only using this generic one
148
+ 10608 E ERRCODE_INVALID_ARGUMENT_FOR_XQUERY invalid_argument_for_xquery
149
+
144
150
  Section: Class 20 - Case Not Found
145
151
 
146
152
  20000 E ERRCODE_CASE_NOT_FOUND case_not_found
@@ -439,6 +445,7 @@ Section: Class 58 - System Error (errors external to PostgreSQL itself)
439
445
  58030 E ERRCODE_IO_ERROR io_error
440
446
  58P01 E ERRCODE_UNDEFINED_FILE undefined_file
441
447
  58P02 E ERRCODE_DUPLICATE_FILE duplicate_file
448
+ 58P03 E ERRCODE_FILE_NAME_TOO_LONG file_name_too_long
442
449
 
443
450
  Section: Class F0 - Configuration File Error
444
451
 
data/ext/extconf.rb CHANGED
@@ -27,13 +27,13 @@ if gem_platform=with_config("cross-build")
27
27
  gem 'mini_portile2', '~>2.1'
28
28
  require 'mini_portile2'
29
29
 
30
- OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '3.5.1'
30
+ OPENSSL_VERSION = ENV['OPENSSL_VERSION'] || '3.6.0'
31
31
  OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
32
32
 
33
- KRB5_VERSION = ENV['KRB5_VERSION'] || '1.21.3'
33
+ KRB5_VERSION = ENV['KRB5_VERSION'] || '1.22.1'
34
34
  KRB5_SOURCE_URI = "http://kerberos.org/dist/krb5/#{KRB5_VERSION[/^(\d+\.\d+)/]}/krb5-#{KRB5_VERSION}.tar.gz"
35
35
 
36
- POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '17.5'
36
+ POSTGRESQL_VERSION = ENV['POSTGRESQL_VERSION'] || '18.1'
37
37
  POSTGRESQL_SOURCE_URI = "http://ftp.postgresql.org/pub/source/v#{POSTGRESQL_VERSION}/postgresql-#{POSTGRESQL_VERSION}.tar.bz2"
38
38
 
39
39
  class BuildRecipe < MiniPortile
@@ -49,6 +49,12 @@ if gem_platform=with_config("cross-build")
49
49
  "#{target}/#{RUBY_PLATFORM}"
50
50
  end
51
51
 
52
+ # Add "--prefix=/", to avoid our actual build install path compiled into the binary.
53
+ # Instead use DESTDIR variable of make to set our install path.
54
+ def configure_prefix
55
+ "--prefix="
56
+ end
57
+
52
58
  def cook_and_activate
53
59
  checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{RUBY_PLATFORM}.installed")
54
60
  unless File.exist?(checkpoint)
@@ -70,13 +76,13 @@ if gem_platform=with_config("cross-build")
70
76
  envs = []
71
77
  envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /mingw|mswin/
72
78
  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")
79
+ execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", "--prefix=/"], altlog: "config.log")
74
80
  end
75
81
  def compile
76
82
  execute('compile', "#{make_cmd} build_libs")
77
83
  end
78
84
  def install
79
- execute('install', "#{make_cmd} install_dev")
85
+ execute('install', "#{make_cmd} install_dev DESTDIR=#{path}")
80
86
  end
81
87
  end
82
88
 
@@ -104,6 +110,9 @@ if gem_platform=with_config("cross-build")
104
110
  end
105
111
  super
106
112
  end
113
+ def install
114
+ execute('install', "#{make_cmd} install DESTDIR=#{path}")
115
+ end
107
116
  end
108
117
  # We specify -fcommon to get around duplicate definition errors in recent gcc.
109
118
  # See https://github.com/cockroachdb/cockroach/issues/49734
@@ -112,6 +121,7 @@ if gem_platform=with_config("cross-build")
112
121
  recipe.configure_options << "--without-keyutils"
113
122
  recipe.configure_options << "--disable-nls"
114
123
  recipe.configure_options << "--disable-silent-rules"
124
+ recipe.configure_options << "--disable-rpath"
115
125
  recipe.configure_options << "--without-system-verto"
116
126
  recipe.configure_options << "krb5_cv_attr_constructor_destructor=yes"
117
127
  recipe.configure_options << "ac_cv_func_regcomp=yes"
@@ -146,12 +156,13 @@ if gem_platform=with_config("cross-build")
146
156
  '--without-zlib',
147
157
  '--without-icu',
148
158
  '--without-readline',
159
+ '--disable-rpath',
149
160
  'ac_cv_search_gss_store_cred_into=',
150
161
  ]
151
162
  end
152
163
  def compile
153
- execute 'compile include', "#{make_cmd} -C src/include install"
154
- execute 'compile interfaces', "#{make_cmd} -C src/interfaces install"
164
+ execute 'compile include', "#{make_cmd} -C src/include install DESTDIR=#{path}"
165
+ execute 'compile interfaces', "#{make_cmd} -C src/interfaces install DESTDIR=#{path}"
155
166
  end
156
167
  def install
157
168
  end
@@ -169,6 +180,9 @@ if gem_platform=with_config("cross-build")
169
180
  # Use our own library name for libpq to avoid loading of system libpq by accident.
170
181
  FileUtils.ln_sf File.join(postgresql_recipe.port_path, "lib/#{libpq_orig}"),
171
182
  File.join(postgresql_recipe.port_path, "lib/#{libpq_rubypg}")
183
+ # Link to libpq_rubypg in our ports directory without adding it as rpath (like dir_config does)
184
+ $CFLAGS << " -I#{postgresql_recipe.path}/include"
185
+ $LDFLAGS << " -L#{postgresql_recipe.path}/lib"
172
186
  # Avoid dependency to external libgcc.dll on x86-mingw32
173
187
  $LDFLAGS << " -static-libgcc" if RUBY_PLATFORM =~ /mingw|mswin/
174
188
  # Avoid: "libpq.so: undefined reference to `dlopen'" in cross-ruby-2.7.8
@@ -176,8 +190,6 @@ if gem_platform=with_config("cross-build")
176
190
  # Find libpq in the ports directory coming from lib/3.x
177
191
  # It is shared between all compiled ruby versions.
178
192
  $LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../ports/#{gem_platform}/lib'" if RUBY_PLATFORM =~ /linux/
179
- # Don't use pg_config for cross build, but --with-pg-* path options
180
- dir_config('pg', "#{postgresql_recipe.path}/include", "#{postgresql_recipe.path}/lib")
181
193
 
182
194
  $defs.push( "-DPG_IS_BINARY_GEM")
183
195
  else
@@ -307,6 +319,7 @@ have_func 'PQsetChunkedRowsMode', 'libpq-fe.h' # since PostgreSQL-17
307
319
  have_func 'timegm'
308
320
  have_func 'rb_io_wait' # since ruby-3.0
309
321
  have_func 'rb_io_descriptor' # since ruby-3.1
322
+ have_func 'rb_hash_new_capa' # since ruby-3.2
310
323
 
311
324
  have_header 'inttypes.h'
312
325
  have_header('ruby/fiber/scheduler.h') if RUBY_PLATFORM=~/mingw|mswin/
@@ -318,3 +331,20 @@ end
318
331
  create_header()
319
332
  create_makefile( "pg_ext" )
320
333
 
334
+ if gem_platform
335
+ # exercise the strip command on native binary gems
336
+ # This approach borrowed from
337
+ # https://github.com/rake-compiler/rake-compiler-dock/blob/38066d479050f4fdb3956469255b35a05e5949ef/test/rcd_test/ext/mri/extconf.rb#L97C1-L110C42
338
+ strip_tool = RbConfig::CONFIG['STRIP']
339
+ strip_tool += ' -x' if RUBY_PLATFORM =~ /darwin/
340
+ File.open('Makefile.new', 'w') do |o|
341
+ o.puts 'hijack: all strip'
342
+ o.puts
343
+ o.write(File.read('Makefile'))
344
+ o.puts
345
+ o.puts 'strip: $(DLLIB)'
346
+ o.puts "\t$(ECHO) Stripping $(DLLIB)"
347
+ o.puts "\t$(Q) #{strip_tool} $(DLLIB)"
348
+ end
349
+ File.rename('Makefile.new', 'Makefile')
350
+ end
data/ext/pg.h CHANGED
@@ -76,6 +76,10 @@ typedef long suseconds_t;
76
76
  #define PG_MAX_COLUMNS 4000
77
77
  #endif
78
78
 
79
+ #ifndef HAVE_RB_HASH_NEW_CAPA
80
+ #define rb_hash_new_capa(x) rb_hash_new()
81
+ #endif
82
+
79
83
  #define pg_gc_location(x) x = rb_gc_location(x)
80
84
 
81
85
  /* For compatibility with ruby < 3.0 */
@@ -157,10 +161,8 @@ typedef struct {
157
161
  /* Size of PGresult as published to ruby memory management. */
158
162
  ssize_t result_size;
159
163
 
160
- /* Prefilled tuple Hash with fnames[] as keys. */
161
- VALUE tuple_hash;
162
-
163
- /* Hash with fnames[] to field number mapping. */
164
+ /* Hash with fnames[] to field number mapping.
165
+ * Init on-demand to create PG::Tuple objects, otherwise Qnil. */
164
166
  VALUE field_map;
165
167
 
166
168
  /* List of field names as frozen String or Symbol objects.
@@ -117,7 +117,7 @@ pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int
117
117
  /* create a buffer of the encoded length */
118
118
  VALUE out_value = rb_str_new(NULL, encoded_len);
119
119
 
120
- base64_encode( RSTRING_PTR(out_value), val, len );
120
+ rbpg_base64_encode( RSTRING_PTR(out_value), val, len );
121
121
 
122
122
  /* Is it a pure String conversion? Then we can directly send out_value to the user. */
123
123
  if( this->comp.format == 0 && dec_func == pg_text_dec_string ){
@@ -524,7 +524,7 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
524
524
  if(out){
525
525
  /* Second encoder pass, if required */
526
526
  strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
527
- strlen = base64_decode( out, out, strlen );
527
+ strlen = rbpg_base64_decode( out, out, strlen );
528
528
 
529
529
  return strlen;
530
530
  } else {
@@ -538,7 +538,7 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
538
538
  strlen = RSTRING_LENINT(subint);
539
539
  out_str = rb_str_new(NULL, BASE64_DECODED_SIZE(strlen));
540
540
 
541
- strlen = base64_decode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
541
+ strlen = rbpg_base64_decode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
542
542
  rb_str_set_len( out_str, strlen );
543
543
  *intermediate = out_str;
544
544
 
data/ext/pg_connection.c CHANGED
@@ -66,6 +66,7 @@ pg_get_connection_safe( VALUE self )
66
66
  t_pg_connection *this;
67
67
  TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
68
68
 
69
+ rb_check_frozen(self);
69
70
  if ( !this->pgconn )
70
71
  pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
71
72
 
@@ -2382,7 +2383,7 @@ pgconn_notifies(VALUE self)
2382
2383
  return Qnil;
2383
2384
  }
2384
2385
 
2385
- hash = rb_hash_new();
2386
+ hash = rb_hash_new_capa(3);
2386
2387
  relname = rb_str_new2(notification->relname);
2387
2388
  be_pid = INT2NUM(notification->be_pid);
2388
2389
  extra = rb_str_new2(notification->extra);
@@ -4425,9 +4426,11 @@ pgconn_set_default_encoding( VALUE self )
4425
4426
  * res.type_map_for_queries = typemap
4426
4427
  *
4427
4428
  * Set the default TypeMap that is used for type casts of query bind parameters.
4429
+ * It can be overwritten per +type_map+ parameter of #exec_params and siblings.
4428
4430
  *
4429
4431
  * +typemap+ must be a kind of PG::TypeMap .
4430
4432
  *
4433
+ * See also #type_map_for_queries
4431
4434
  */
4432
4435
  static VALUE
4433
4436
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
@@ -4452,6 +4455,9 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
4452
4455
  * Returns the default TypeMap that is currently set for type casts of query
4453
4456
  * bind parameters.
4454
4457
  *
4458
+ * Default is PG::TypeMapAllStrings .
4459
+ *
4460
+ * See also #type_map_for_queries=
4455
4461
  */
4456
4462
  static VALUE
4457
4463
  pgconn_type_map_for_queries_get(VALUE self)
@@ -4466,9 +4472,11 @@ pgconn_type_map_for_queries_get(VALUE self)
4466
4472
  * res.type_map_for_results = typemap
4467
4473
  *
4468
4474
  * Set the default TypeMap that is used for type casts of result values.
4475
+ * It can be overwritten per PG::Result#type_map= .
4469
4476
  *
4470
4477
  * +typemap+ must be a kind of PG::TypeMap .
4471
4478
  *
4479
+ * See also #type_map_for_results
4472
4480
  */
4473
4481
  static VALUE
4474
4482
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
@@ -4490,6 +4498,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
4490
4498
  *
4491
4499
  * Returns the default TypeMap that is currently set for type casts of result values.
4492
4500
  *
4501
+ * Default is PG::TypeMapAllStrings .
4502
+ *
4503
+ * See also #type_map_for_results=
4493
4504
  */
4494
4505
  static VALUE
4495
4506
  pgconn_type_map_for_results_get(VALUE self)
@@ -4506,11 +4517,13 @@ pgconn_type_map_for_results_get(VALUE self)
4506
4517
  *
4507
4518
  * Set the default coder that is used for type casting of parameters
4508
4519
  * to #put_copy_data .
4520
+ * It can be overwritten per +encoder+ parameter of #put_copy_data and +coder+ parameter of #copy_data.
4509
4521
  *
4510
4522
  * +encoder+ can be:
4511
4523
  * * a kind of PG::Coder
4512
4524
  * * +nil+ - disable type encoding, data must be a String.
4513
4525
  *
4526
+ * See also #encoder_for_put_copy_data
4514
4527
  */
4515
4528
  static VALUE
4516
4529
  pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
@@ -4540,6 +4553,8 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
4540
4553
  * * a kind of PG::Coder
4541
4554
  * * +nil+ - type encoding is disabled, data must be a String.
4542
4555
  *
4556
+ * Default is +nil+ .
4557
+ * See also #encoder_for_put_copy_data=
4543
4558
  */
4544
4559
  static VALUE
4545
4560
  pgconn_encoder_for_put_copy_data_get(VALUE self)
@@ -4555,11 +4570,13 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
4555
4570
  *
4556
4571
  * Set the default coder that is used for type casting of received data
4557
4572
  * by #get_copy_data .
4573
+ * It can be overwritten per +decoder+ parameter of #get_copy_data and +coder+ parameter of #copy_data.
4558
4574
  *
4559
4575
  * +decoder+ can be:
4560
4576
  * * a kind of PG::Coder
4561
4577
  * * +nil+ - disable type decoding, returned data will be a String.
4562
4578
  *
4579
+ * See also #decoder_for_get_copy_data
4563
4580
  */
4564
4581
  static VALUE
4565
4582
  pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
@@ -4589,6 +4606,9 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4589
4606
  * * a kind of PG::Coder
4590
4607
  * * +nil+ - type encoding is disabled, returned data will be a String.
4591
4608
  *
4609
+ * Default is +nil+ .
4610
+ *
4611
+ * See also #decoder_for_get_copy_data=
4592
4612
  */
4593
4613
  static VALUE
4594
4614
  pgconn_decoder_for_get_copy_data_get(VALUE self)
@@ -4611,7 +4631,7 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
4611
4631
  *
4612
4632
  * Settings the type of field names affects only future results.
4613
4633
  *
4614
- * See further description at PG::Result#field_name_type=
4634
+ * See further description at PG::Result#field_name_type= and #field_name_type .
4615
4635
  *
4616
4636
  */
4617
4637
  static VALUE