pg 1.5.4 → 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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/{History.md → CHANGELOG.md} +132 -4
  4. data/Gemfile +15 -6
  5. data/README-Windows.rdoc +1 -1
  6. data/README.ja.md +4 -4
  7. data/README.md +66 -23
  8. data/Rakefile +81 -14
  9. data/certs/kanis@comcard.de.pem +20 -0
  10. data/certs/larskanis-2024.pem +24 -0
  11. data/ext/errorcodes.def +11 -3
  12. data/ext/errorcodes.rb +1 -1
  13. data/ext/errorcodes.txt +9 -5
  14. data/ext/extconf.rb +192 -15
  15. data/ext/gvl_wrappers.c +13 -2
  16. data/ext/gvl_wrappers.h +33 -0
  17. data/ext/pg.c +17 -6
  18. data/ext/pg.h +15 -13
  19. data/ext/pg_binary_decoder.c +153 -1
  20. data/ext/pg_binary_encoder.c +213 -10
  21. data/ext/pg_cancel_connection.c +360 -0
  22. data/ext/pg_coder.c +54 -5
  23. data/ext/pg_connection.c +431 -169
  24. data/ext/pg_copy_coder.c +19 -15
  25. data/ext/pg_record_coder.c +7 -7
  26. data/ext/pg_result.c +106 -54
  27. data/ext/pg_text_decoder.c +5 -2
  28. data/ext/pg_text_encoder.c +39 -20
  29. data/ext/pg_tuple.c +8 -8
  30. data/ext/pg_type_map.c +4 -2
  31. data/ext/pg_type_map_all_strings.c +1 -1
  32. data/ext/pg_type_map_by_class.c +1 -1
  33. data/ext/pg_type_map_by_column.c +2 -1
  34. data/ext/pg_type_map_by_mri_type.c +1 -1
  35. data/ext/pg_type_map_by_oid.c +3 -1
  36. data/ext/pg_type_map_in_ruby.c +1 -1
  37. data/ext/pg_util.c +2 -2
  38. data/ext/pg_util.h +2 -2
  39. data/lib/pg/basic_type_map_for_queries.rb +15 -7
  40. data/lib/pg/basic_type_registry.rb +16 -4
  41. data/lib/pg/cancel_connection.rb +53 -0
  42. data/lib/pg/coder.rb +4 -2
  43. data/lib/pg/connection.rb +310 -167
  44. data/lib/pg/exceptions.rb +6 -0
  45. data/lib/pg/text_decoder/date.rb +3 -0
  46. data/lib/pg/text_decoder/json.rb +3 -0
  47. data/lib/pg/text_encoder/date.rb +1 -0
  48. data/lib/pg/text_encoder/inet.rb +3 -0
  49. data/lib/pg/text_encoder/json.rb +3 -0
  50. data/lib/pg/version.rb +2 -1
  51. data/lib/pg.rb +156 -120
  52. data/misc/glibc/Dockerfile +20 -0
  53. data/misc/glibc/docker-compose.yml +9 -0
  54. data/misc/glibc/glibc_spec.rb +5 -0
  55. data/misc/yugabyte/Dockerfile +9 -0
  56. data/misc/yugabyte/docker-compose.yml +28 -0
  57. data/misc/yugabyte/pg-test.rb +45 -0
  58. data/pg.gemspec +8 -4
  59. data/ports/patches/krb5/1.22.1/0001-Allow-static-linking-krb5-library.patch +30 -0
  60. data/ports/patches/krb5/1.22.1/0002-unknown-command-line-option-on-clang.patch +12 -0
  61. data/ports/patches/openssl/3.5.2/0001-aarch64-mingw.patch +21 -0
  62. data/ports/patches/postgresql/18.1/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
  63. data/ports/patches/postgresql/18.1/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
  64. data/rakelib/pg_gem_helper.rb +64 -0
  65. data.tar.gz.sig +0 -0
  66. metadata +49 -47
  67. metadata.gz.sig +0 -0
  68. data/.appveyor.yml +0 -42
  69. data/.gems +0 -6
  70. data/.gemtest +0 -0
  71. data/.github/workflows/binary-gems.yml +0 -117
  72. data/.github/workflows/source-gem.yml +0 -141
  73. data/.gitignore +0 -22
  74. data/.hgsigs +0 -34
  75. data/.hgtags +0 -41
  76. data/.irbrc +0 -23
  77. data/.pryrc +0 -23
  78. data/.tm_properties +0 -21
  79. data/.travis.yml +0 -49
  80. data/Manifest.txt +0 -72
  81. data/Rakefile.cross +0 -298
  82. data/translation/.po4a-version +0 -7
  83. data/translation/po/all.pot +0 -936
  84. data/translation/po/ja.po +0 -1036
  85. data/translation/po4a.cfg +0 -12
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 );
@@ -453,6 +458,10 @@
453
458
  VALUE klass = define_error_class( "IdleInTransactionSessionTimeout", "25" );
454
459
  register_error_class( "25P03", klass );
455
460
  }
461
+ {
462
+ VALUE klass = define_error_class( "TransactionTimeout", "25" );
463
+ register_error_class( "25P04", klass );
464
+ }
456
465
  {
457
466
  VALUE klass = define_error_class( "InvalidSqlStatementName", NULL );
458
467
  register_error_class( "26000", klass );
@@ -886,9 +895,8 @@
886
895
  register_error_class( "58P02", klass );
887
896
  }
888
897
  {
889
- VALUE klass = define_error_class( "SnapshotTooOld", NULL );
890
- register_error_class( "72000", klass );
891
- register_error_class( "72", klass );
898
+ VALUE klass = define_error_class( "FileNameTooLong", "58" );
899
+ register_error_class( "58P03", klass );
892
900
  }
893
901
  {
894
902
  VALUE klass = define_error_class( "ConfigFileError", NULL );
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-2022, 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
@@ -252,6 +258,7 @@ Section: Class 25 - Invalid Transaction State
252
258
  25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
253
259
  25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
254
260
  25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
261
+ 25P04 E ERRCODE_TRANSACTION_TIMEOUT transaction_timeout
255
262
 
256
263
  Section: Class 26 - Invalid SQL Statement Name
257
264
 
@@ -438,10 +445,7 @@ Section: Class 58 - System Error (errors external to PostgreSQL itself)
438
445
  58030 E ERRCODE_IO_ERROR io_error
439
446
  58P01 E ERRCODE_UNDEFINED_FILE undefined_file
440
447
  58P02 E ERRCODE_DUPLICATE_FILE duplicate_file
441
-
442
- Section: Class 72 - Snapshot Failure
443
- # (class borrowed from Oracle)
444
- 72000 E ERRCODE_SNAPSHOT_TOO_OLD snapshot_too_old
448
+ 58P03 E ERRCODE_FILE_NAME_TOO_LONG file_name_too_long
445
449
 
446
450
  Section: Class F0 - Configuration File Error
447
451
 
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,6 +8,8 @@ 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' )
@@ -22,12 +23,175 @@ else
22
23
  $stderr.puts "Calling libpq with GVL locked"
23
24
  end
24
25
 
25
- if enable_config("windows-cross")
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.6.0'
31
+ OPENSSL_SOURCE_URI = "http://www.openssl.org/source/openssl-#{OPENSSL_VERSION}.tar.gz"
32
+
33
+ KRB5_VERSION = ENV['KRB5_VERSION'] || '1.22.1'
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'] || '18.1'
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
+ # 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
+
58
+ def cook_and_activate
59
+ checkpoint = File.join(self.target, "#{self.name}-#{self.version}-#{RUBY_PLATFORM}.installed")
60
+ unless File.exist?(checkpoint)
61
+ self.cook
62
+ FileUtils.touch checkpoint
63
+ end
64
+ self.activate
65
+ self
66
+ end
67
+ end
68
+
69
+ openssl_platform = with_config("openssl-platform")
70
+ toolchain = with_config("toolchain")
71
+
72
+ openssl_recipe = BuildRecipe.new("openssl", OPENSSL_VERSION, [OPENSSL_SOURCE_URI]).tap do |recipe|
73
+ class << recipe
74
+ attr_accessor :openssl_platform
75
+ def configure
76
+ envs = []
77
+ envs << "CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /mingw|mswin/
78
+ envs << "CFLAGS=-fPIC -DOPENSSL_THREADS" if RUBY_PLATFORM =~ /linux|darwin/
79
+ execute('configure', ['env', *envs, "./Configure", openssl_platform, "threads", "-static", "CROSS_COMPILE=#{host}-", "--prefix=/"], altlog: "config.log")
80
+ end
81
+ def compile
82
+ execute('compile', "#{make_cmd} build_libs")
83
+ end
84
+ def install
85
+ execute('install', "#{make_cmd} install_dev DESTDIR=#{path}")
86
+ end
87
+ end
88
+
89
+ recipe.openssl_platform = openssl_platform
90
+ recipe.host = toolchain
91
+ recipe.cook_and_activate
92
+ end
93
+
94
+ if RUBY_PLATFORM =~ /linux|darwin/
95
+ krb5_recipe = BuildRecipe.new("krb5", KRB5_VERSION, [KRB5_SOURCE_URI]).tap do |recipe|
96
+ class << recipe
97
+ def work_path
98
+ File.join(super, "src")
99
+ end
100
+ def configure
101
+ if RUBY_PLATFORM=~/darwin/
102
+ ENV["CC"] = host[/^.*[^\.\d]/] + "-clang"
103
+ ENV["CXX"] = host[/^.*[^\.\d]/] + "-c++"
104
+
105
+ # Manually set the correct values for configure checks that libkrb5 won't be
106
+ # able to perform because we're cross-compiling.
107
+ ENV["krb5_cv_attr_constructor_destructor"] = "yes"
108
+ ENV["ac_cv_func_regcomp"] = "yes"
109
+ ENV["ac_cv_printf_positional"] = "yes"
110
+ end
111
+ super
112
+ end
113
+ def install
114
+ execute('install', "#{make_cmd} install DESTDIR=#{path}")
115
+ end
116
+ end
117
+ # We specify -fcommon to get around duplicate definition errors in recent gcc.
118
+ # See https://github.com/cockroachdb/cockroach/issues/49734
119
+ recipe.configure_options << "CFLAGS=-fcommon#{" -fPIC" if RUBY_PLATFORM =~ /linux/}"
120
+ recipe.configure_options << "LDFLAGS=-framework Kerberos" if RUBY_PLATFORM =~ /darwin/
121
+ recipe.configure_options << "--without-keyutils"
122
+ recipe.configure_options << "--disable-nls"
123
+ recipe.configure_options << "--disable-silent-rules"
124
+ recipe.configure_options << "--disable-rpath"
125
+ recipe.configure_options << "--without-system-verto"
126
+ recipe.configure_options << "krb5_cv_attr_constructor_destructor=yes"
127
+ recipe.configure_options << "ac_cv_func_regcomp=yes"
128
+ recipe.configure_options << "ac_cv_printf_positional=yes"
129
+ recipe.host = toolchain
130
+ recipe.cook_and_activate
131
+ end
132
+ end
133
+
134
+ # We build a libpq library file which static links OpenSSL and krb5.
135
+ # Our builtin libpq is referenced in different ways depending on the OS:
136
+ # - Window: Add the ports directory at runtime per RubyInstaller::Runtime.add_dll_directory
137
+ # The file is called "libpq.dll"
138
+ # - Linux: Add a rpath to pg_ext.so which references the ports directory.
139
+ # The file is called "libpq-ruby-pg.so.1" to avoid loading of system libpq by accident.
140
+ # - Macos: Add a reference with relative path in pg_ext.so to the ports directory.
141
+ # The file is called "libpq-ruby-pg.1.dylib" to avoid loading of other libpq by accident.
142
+ libpq_orig, libpq_rubypg = case RUBY_PLATFORM
143
+ when /linux/ then ["libpq.so.5", "libpq-ruby-pg.so.1"]
144
+ when /darwin/ then ["libpq.5.dylib", "libpq-ruby-pg.1.dylib"]
145
+ # when /mingw/ then ["libpq.dll", "libpq.dll"] # renaming not needed
146
+ end
147
+
148
+ postgresql_recipe = BuildRecipe.new("postgresql", POSTGRESQL_VERSION, [POSTGRESQL_SOURCE_URI]).tap do |recipe|
149
+ class << recipe
150
+ def configure_defaults
151
+ [
152
+ "--target=#{host}",
153
+ "--host=#{host}",
154
+ '--with-openssl',
155
+ *(RUBY_PLATFORM=~/linux|darwin/ ? ['--with-gssapi'] : []),
156
+ '--without-zlib',
157
+ '--without-icu',
158
+ '--without-readline',
159
+ '--disable-rpath',
160
+ 'ac_cv_search_gss_store_cred_into=',
161
+ ]
162
+ end
163
+ def compile
164
+ execute 'compile include', "#{make_cmd} -C src/include install DESTDIR=#{path}"
165
+ execute 'compile interfaces', "#{make_cmd} -C src/interfaces install DESTDIR=#{path}"
166
+ end
167
+ def install
168
+ end
169
+ end
170
+
171
+ recipe.host = toolchain
172
+ recipe.configure_options << "CFLAGS=#{" -fPIC" if RUBY_PLATFORM =~ /linux|darwin/}"
173
+ 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/}"
174
+ recipe.configure_options << "LIBS=-lkrb5 -lcom_err -lk5crypto -lkrb5support -lresolv" if RUBY_PLATFORM =~ /linux/
175
+ recipe.configure_options << "LIBS=-lssl -lwsock32 -lgdi32 -lws2_32 -lcrypt32" if RUBY_PLATFORM =~ /mingw|mswin/
176
+ recipe.configure_options << "CPPFLAGS=-I#{openssl_recipe.path}/include"
177
+ recipe.cook_and_activate
178
+ end
179
+
180
+ # Use our own library name for libpq to avoid loading of system libpq by accident.
181
+ FileUtils.ln_sf File.join(postgresql_recipe.port_path, "lib/#{libpq_orig}"),
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"
26
186
  # Avoid dependency to external libgcc.dll on x86-mingw32
27
- $LDFLAGS << " -static-libgcc"
28
- # Don't use pg_config for cross build, but --with-pg-* path options
29
- dir_config 'pg'
187
+ $LDFLAGS << " -static-libgcc" if RUBY_PLATFORM =~ /mingw|mswin/
188
+ # Avoid: "libpq.so: undefined reference to `dlopen'" in cross-ruby-2.7.8
189
+ $LDFLAGS << " -Wl,--no-as-needed" if RUBY_PLATFORM !~ /aarch64|arm64|darwin/
190
+ # Find libpq in the ports directory coming from lib/3.x
191
+ # It is shared between all compiled ruby versions.
192
+ $LDFLAGS << " '-Wl,-rpath=$$ORIGIN/../../ports/#{gem_platform}/lib'" if RUBY_PLATFORM =~ /linux/
30
193
 
194
+ $defs.push( "-DPG_IS_BINARY_GEM")
31
195
  else
32
196
  # Native build
33
197
 
@@ -77,7 +241,7 @@ $INSTALLFILES = {
77
241
  "./postgresql_lib_path.rb" => "$(RUBYLIBDIR)/pg/"
78
242
  }
79
243
 
80
- if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
244
+ if /solaris/ =~ RUBY_PLATFORM
81
245
  append_cppflags( '-D__EXTENSIONS__' )
82
246
  end
83
247
 
@@ -142,25 +306,21 @@ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
142
306
  end
143
307
  end
144
308
 
145
- have_func 'PQconninfo', 'libpq-fe.h' or
309
+ have_func 'PQencryptPasswordConn', 'libpq-fe.h' or # since PostgreSQL-10
146
310
  abort "Your PostgreSQL is too old. Either install an older version " +
147
- "of this gem or upgrade your database to at least PostgreSQL-9.3."
311
+ "of this gem or upgrade your database to at least PostgreSQL-10."
148
312
  # optional headers/functions
149
- have_func 'PQsslAttribute', 'libpq-fe.h' # since PostgreSQL-9.5
150
- have_func 'PQresultVerboseErrorMessage', 'libpq-fe.h' # since PostgreSQL-9.6
151
- have_func 'PQencryptPasswordConn', 'libpq-fe.h' # since PostgreSQL-10
152
313
  have_func 'PQresultMemorySize', 'libpq-fe.h' # since PostgreSQL-12
153
314
  have_func 'PQenterPipelineMode', 'libpq-fe.h' do |src| # since PostgreSQL-14
154
315
  # Ensure header files fit as well
155
316
  src + " int con(){ return PGRES_PIPELINE_SYNC; }"
156
317
  end
318
+ have_func 'PQsetChunkedRowsMode', 'libpq-fe.h' # since PostgreSQL-17
157
319
  have_func 'timegm'
158
- have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
159
- have_func 'rb_gc_mark_movable' # since ruby-2.7
160
320
  have_func 'rb_io_wait' # since ruby-3.0
321
+ have_func 'rb_io_descriptor' # since ruby-3.1
322
+ have_func 'rb_hash_new_capa' # since ruby-3.2
161
323
 
162
- # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
163
- have_header 'unistd.h'
164
324
  have_header 'inttypes.h'
165
325
  have_header('ruby/fiber/scheduler.h') if RUBY_PLATFORM=~/mingw|mswin/
166
326
 
@@ -171,3 +331,20 @@ end
171
331
  create_header()
172
332
  create_makefile( "pg_ext" )
173
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/gvl_wrappers.c CHANGED
@@ -5,8 +5,19 @@
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
 
12
23
  #ifdef ENABLE_GVL_UNLOCK
data/ext/gvl_wrappers.h CHANGED
@@ -21,6 +21,10 @@
21
21
  # include RUBY_EXTCONF_H
22
22
  #endif
23
23
 
24
+ #ifndef HAVE_PQSETCHUNKEDROWSMODE
25
+ typedef struct pg_cancel_conn PGcancelConn;
26
+ #endif
27
+
24
28
  #define DEFINE_PARAM_LIST1(type, name) \
25
29
  name,
26
30
 
@@ -149,6 +153,12 @@
149
153
  #define FOR_EACH_PARAM_OF_PQdescribePortal(param) \
150
154
  param(PGconn *, conn)
151
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
+
152
162
  #define FOR_EACH_PARAM_OF_PQgetResult(param)
153
163
 
154
164
  #define FOR_EACH_PARAM_OF_PQputCopyData(param) \
@@ -196,11 +206,25 @@
196
206
  #define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
197
207
  param(PGconn *, conn)
198
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
+
199
219
  #define FOR_EACH_PARAM_OF_PQsetClientEncoding(param) \
200
220
  param(PGconn *, conn)
201
221
 
202
222
  #define FOR_EACH_PARAM_OF_PQisBusy(param)
203
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
+
204
228
  #define FOR_EACH_PARAM_OF_PQencryptPasswordConn(param) \
205
229
  param(PGconn *, conn) \
206
230
  param(const char *, passwd) \
@@ -225,6 +249,8 @@
225
249
  function(PQprepare, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
226
250
  function(PQdescribePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
227
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) \
228
254
  function(PQgetResult, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
229
255
  function(PQputCopyData, GVL_TYPE_NONVOID, int, int, nbytes) \
230
256
  function(PQputCopyEnd, GVL_TYPE_NONVOID, int, const char *, errormsg) \
@@ -236,8 +262,15 @@
236
262
  function(PQsendQueryPrepared, GVL_TYPE_NONVOID, int, int, resultFormat) \
237
263
  function(PQsendDescribePrepared, GVL_TYPE_NONVOID, int, const char *, stmt) \
238
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) \
239
269
  function(PQsetClientEncoding, GVL_TYPE_NONVOID, int, const char *, encoding) \
240
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) \
241
274
  function(PQencryptPasswordConn, GVL_TYPE_NONVOID, char *, const char *, algorithm) \
242
275
  function(PQcancel, GVL_TYPE_NONVOID, int, int, errbufsize);
243
276
 
data/ext/pg.c CHANGED
@@ -404,6 +404,10 @@ Init_pg_ext(void)
404
404
  /* Checking if server is in standby mode. Available since PostgreSQL-14. */
405
405
  rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_STANDBY", INT2FIX(CONNECTION_CHECK_STANDBY));
406
406
  #endif
407
+ #if PG_MAJORVERSION_NUM >= 17
408
+ /* Waiting for connection attempt to be started. Available since PostgreSQL-17. */
409
+ rb_define_const(rb_mPGconstants, "CONNECTION_ALLOCATED", INT2FIX(CONNECTION_ALLOCATED));
410
+ #endif
407
411
 
408
412
  /****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
409
413
 
@@ -451,14 +455,12 @@ Init_pg_ext(void)
451
455
  rb_define_const(rb_mPGconstants, "PQERRORS_SQLSTATE", INT2FIX(PQERRORS_SQLSTATE));
452
456
  #endif
453
457
 
454
- #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
455
458
  /* See Connection#set_error_context_visibility */
456
459
  rb_define_const(rb_mPGconstants, "PQSHOW_CONTEXT_NEVER", INT2FIX(PQSHOW_CONTEXT_NEVER));
457
460
  /* See Connection#set_error_context_visibility */
458
461
  rb_define_const(rb_mPGconstants, "PQSHOW_CONTEXT_ERRORS", INT2FIX(PQSHOW_CONTEXT_ERRORS));
459
462
  /* See Connection#set_error_context_visibility */
460
463
  rb_define_const(rb_mPGconstants, "PQSHOW_CONTEXT_ALWAYS", INT2FIX(PQSHOW_CONTEXT_ALWAYS));
461
- #endif
462
464
 
463
465
  /****** PG::Connection CLASS CONSTANTS: Check Server Status ******/
464
466
 
@@ -506,6 +508,10 @@ Init_pg_ext(void)
506
508
  rb_define_const(rb_mPGconstants, "PGRES_COPY_BOTH", INT2FIX(PGRES_COPY_BOTH));
507
509
  /* Result#result_status constant - Single tuple from larger resultset. */
508
510
  rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
511
+ #ifdef HAVE_PQSETCHUNKEDROWSMODE
512
+ /* Result#result_status constant - tuple chunk from larger resultset. */
513
+ rb_define_const(rb_mPGconstants, "PGRES_TUPLES_CHUNK", INT2FIX(PGRES_TUPLES_CHUNK));
514
+ #endif
509
515
 
510
516
  #ifdef HAVE_PQENTERPIPELINEMODE
511
517
  /* Result#result_status constant - The PG::Result represents a synchronization point in pipeline mode, requested by Connection#pipeline_sync.
@@ -530,20 +536,18 @@ Init_pg_ext(void)
530
536
  */
531
537
  rb_define_const(rb_mPGconstants, "PG_DIAG_SEVERITY", INT2FIX(PG_DIAG_SEVERITY));
532
538
 
533
- #ifdef PG_DIAG_SEVERITY_NONLOCALIZED
534
539
  /* Result#result_error_field argument constant
535
540
  *
536
541
  * The severity; the field contents are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message).
537
542
  * This is identical to the PG_DIAG_SEVERITY field except that the contents are never localized.
538
543
  *
539
- * Available since PostgreSQL-9.6
540
544
  */
541
545
  rb_define_const(rb_mPGconstants, "PG_DIAG_SEVERITY_NONLOCALIZED", INT2FIX(PG_DIAG_SEVERITY_NONLOCALIZED));
542
- #endif
546
+
543
547
  /* Result#result_error_field argument constant
544
548
  *
545
549
  * The SQLSTATE code for the error.
546
- * The SQLSTATE code identies the type of error that has occurred; it can be used by front-end applications to perform specific operations (such as error handling) in response to a particular database error.
550
+ * The SQLSTATE code identifies the type of error that has occurred; it can be used by front-end applications to perform specific operations (such as error handling) in response to a particular database error.
547
551
  * For a list of the possible SQLSTATE codes, see Appendix A.
548
552
  * This field is not localizable, and is always present.
549
553
  */
@@ -667,6 +671,12 @@ Init_pg_ext(void)
667
671
  /* PostgreSQL compiled in default port */
668
672
  rb_define_const(rb_mPGconstants, "DEF_PGPORT", INT2FIX(DEF_PGPORT));
669
673
 
674
+ #ifdef PG_IS_BINARY_GEM
675
+ rb_define_const(rb_mPG, "IS_BINARY_GEM", Qtrue);
676
+ #else
677
+ rb_define_const(rb_mPG, "IS_BINARY_GEM", Qfalse);
678
+ #endif
679
+
670
680
  /* Add the constants to the toplevel namespace */
671
681
  rb_include_module( rb_mPG, rb_mPGconstants );
672
682
 
@@ -689,4 +699,5 @@ Init_pg_ext(void)
689
699
  init_pg_copycoder();
690
700
  init_pg_recordcoder();
691
701
  init_pg_tuple();
702
+ init_pg_cancon();
692
703
  }
data/ext/pg.h CHANGED
@@ -76,15 +76,12 @@ typedef long suseconds_t;
76
76
  #define PG_MAX_COLUMNS 4000
77
77
  #endif
78
78
 
79
- #ifdef HAVE_RB_GC_MARK_MOVABLE
80
- #define pg_compact_callback(x) (x)
81
- #define pg_gc_location(x) x = rb_gc_location(x)
82
- #else
83
- #define rb_gc_mark_movable(x) rb_gc_mark(x)
84
- #define pg_compact_callback(x) {(x)}
85
- #define pg_gc_location(x) UNUSED(x)
79
+ #ifndef HAVE_RB_HASH_NEW_CAPA
80
+ #define rb_hash_new_capa(x) rb_hash_new()
86
81
  #endif
87
82
 
83
+ #define pg_gc_location(x) x = rb_gc_location(x)
84
+
88
85
  /* For compatibility with ruby < 3.0 */
89
86
  #ifndef RUBY_TYPED_FROZEN_SHAREABLE
90
87
  #define PG_RUBY_TYPED_FROZEN_SHAREABLE 0
@@ -123,10 +120,8 @@ typedef struct {
123
120
  /* enable automatic flushing of send data at the end of send_query calls */
124
121
  unsigned int flush_data : 1;
125
122
 
126
- #if defined(_WIN32)
127
123
  /* File descriptor to be used for rb_w32_unwrap_io_handle() */
128
124
  int ruby_sd;
129
- #endif
130
125
  } t_pg_connection;
131
126
 
132
127
  typedef struct pg_coder t_pg_coder;
@@ -166,10 +161,8 @@ typedef struct {
166
161
  /* Size of PGresult as published to ruby memory management. */
167
162
  ssize_t result_size;
168
163
 
169
- /* Prefilled tuple Hash with fnames[] as keys. */
170
- VALUE tuple_hash;
171
-
172
- /* 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. */
173
166
  VALUE field_map;
174
167
 
175
168
  /* List of field names as frozen String or Symbol objects.
@@ -215,6 +208,7 @@ typedef struct {
215
208
  t_pg_coder comp;
216
209
  t_pg_coder *elem;
217
210
  int needs_quotation;
211
+ int dimensions;
218
212
  char delimiter;
219
213
  } t_pg_composite_coder;
220
214
 
@@ -312,6 +306,7 @@ void init_pg_text_decoder _(( void ));
312
306
  void init_pg_binary_encoder _(( void ));
313
307
  void init_pg_binary_decoder _(( void ));
314
308
  void init_pg_tuple _(( void ));
309
+ void init_pg_cancon _(( void ));
315
310
  VALUE lookup_error_class _(( const char * ));
316
311
  VALUE pg_bin_dec_bytea _(( t_pg_coder*, const char *, int, int, int, int ));
317
312
  VALUE pg_text_dec_string _(( t_pg_coder*, const char *, int, int, int, int ));
@@ -351,6 +346,13 @@ void pg_typemap_compact _(( void * ));
351
346
  PGconn *pg_get_pgconn _(( VALUE ));
352
347
  t_pg_connection *pg_get_connection _(( VALUE ));
353
348
  VALUE pgconn_block _(( int, VALUE *, VALUE ));
349
+ #ifdef __GNUC__
350
+ __attribute__((format(printf, 3, 4)))
351
+ #endif
352
+ NORETURN(void pg_raise_conn_error _(( VALUE klass, VALUE self, const char *format, ...)));
353
+ VALUE pg_wrap_socket_io _(( int sd, VALUE self, VALUE *p_socket_io, int *p_ruby_sd ));
354
+ void pg_unwrap_socket_io _(( VALUE self, VALUE *p_socket_io, int ruby_sd ));
355
+
354
356
 
355
357
  VALUE pg_new_result _(( PGresult *, VALUE ));
356
358
  VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));