pg 1.2.3 → 1.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +42 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +117 -0
  6. data/.github/workflows/source-gem.yml +141 -0
  7. data/.gitignore +22 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +17 -0
  15. data/History.md +901 -0
  16. data/Manifest.txt +0 -1
  17. data/README.ja.md +300 -0
  18. data/README.md +286 -0
  19. data/Rakefile +36 -135
  20. data/Rakefile.cross +13 -13
  21. data/certs/ged.pem +24 -0
  22. data/certs/kanis@comcard.de.pem +20 -0
  23. data/certs/larskanis-2022.pem +26 -0
  24. data/certs/larskanis-2023.pem +24 -0
  25. data/certs/larskanis-2024.pem +24 -0
  26. data/ext/errorcodes.def +12 -0
  27. data/ext/errorcodes.rb +0 -0
  28. data/ext/errorcodes.txt +4 -1
  29. data/ext/extconf.rb +104 -25
  30. data/ext/gvl_wrappers.c +4 -0
  31. data/ext/gvl_wrappers.h +23 -0
  32. data/ext/pg.c +73 -58
  33. data/ext/pg.h +28 -5
  34. data/ext/pg_binary_decoder.c +80 -1
  35. data/ext/pg_binary_encoder.c +225 -1
  36. data/ext/pg_coder.c +96 -33
  37. data/ext/pg_connection.c +1032 -704
  38. data/ext/pg_copy_coder.c +351 -33
  39. data/ext/pg_errors.c +1 -1
  40. data/ext/pg_record_coder.c +50 -19
  41. data/ext/pg_result.c +177 -64
  42. data/ext/pg_text_decoder.c +29 -11
  43. data/ext/pg_text_encoder.c +29 -16
  44. data/ext/pg_tuple.c +83 -60
  45. data/ext/pg_type_map.c +44 -10
  46. data/ext/pg_type_map_all_strings.c +17 -3
  47. data/ext/pg_type_map_by_class.c +54 -27
  48. data/ext/pg_type_map_by_column.c +73 -31
  49. data/ext/pg_type_map_by_mri_type.c +48 -19
  50. data/ext/pg_type_map_by_oid.c +59 -27
  51. data/ext/pg_type_map_in_ruby.c +55 -21
  52. data/ext/pg_util.c +2 -2
  53. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  54. data/lib/pg/basic_type_map_for_queries.rb +202 -0
  55. data/lib/pg/basic_type_map_for_results.rb +104 -0
  56. data/lib/pg/basic_type_registry.rb +303 -0
  57. data/lib/pg/binary_decoder/date.rb +9 -0
  58. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  59. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  60. data/lib/pg/coder.rb +15 -13
  61. data/lib/pg/connection.rb +752 -83
  62. data/lib/pg/exceptions.rb +14 -1
  63. data/lib/pg/text_decoder/date.rb +18 -0
  64. data/lib/pg/text_decoder/inet.rb +9 -0
  65. data/lib/pg/text_decoder/json.rb +14 -0
  66. data/lib/pg/text_decoder/numeric.rb +9 -0
  67. data/lib/pg/text_decoder/timestamp.rb +30 -0
  68. data/lib/pg/text_encoder/date.rb +12 -0
  69. data/lib/pg/text_encoder/inet.rb +28 -0
  70. data/lib/pg/text_encoder/json.rb +14 -0
  71. data/lib/pg/text_encoder/numeric.rb +9 -0
  72. data/lib/pg/text_encoder/timestamp.rb +24 -0
  73. data/lib/pg/version.rb +4 -0
  74. data/lib/pg.rb +94 -39
  75. data/misc/openssl-pg-segfault.rb +31 -0
  76. data/misc/postgres/History.txt +9 -0
  77. data/misc/postgres/Manifest.txt +5 -0
  78. data/misc/postgres/README.txt +21 -0
  79. data/misc/postgres/Rakefile +21 -0
  80. data/misc/postgres/lib/postgres.rb +16 -0
  81. data/misc/ruby-pg/History.txt +9 -0
  82. data/misc/ruby-pg/Manifest.txt +5 -0
  83. data/misc/ruby-pg/README.txt +21 -0
  84. data/misc/ruby-pg/Rakefile +21 -0
  85. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  86. data/pg.gemspec +34 -0
  87. data/rakelib/task_extension.rb +46 -0
  88. data/sample/array_insert.rb +20 -0
  89. data/sample/async_api.rb +102 -0
  90. data/sample/async_copyto.rb +39 -0
  91. data/sample/async_mixed.rb +56 -0
  92. data/sample/check_conn.rb +21 -0
  93. data/sample/copydata.rb +71 -0
  94. data/sample/copyfrom.rb +81 -0
  95. data/sample/copyto.rb +19 -0
  96. data/sample/cursor.rb +21 -0
  97. data/sample/disk_usage_report.rb +177 -0
  98. data/sample/issue-119.rb +94 -0
  99. data/sample/losample.rb +69 -0
  100. data/sample/minimal-testcase.rb +17 -0
  101. data/sample/notify_wait.rb +72 -0
  102. data/sample/pg_statistics.rb +285 -0
  103. data/sample/replication_monitor.rb +222 -0
  104. data/sample/test_binary_values.rb +33 -0
  105. data/sample/wal_shipper.rb +434 -0
  106. data/sample/warehouse_partitions.rb +311 -0
  107. data.tar.gz.sig +0 -0
  108. metadata +137 -210
  109. metadata.gz.sig +0 -0
  110. data/ChangeLog +0 -0
  111. data/History.rdoc +0 -578
  112. data/README.ja.rdoc +0 -13
  113. data/README.rdoc +0 -213
  114. data/lib/pg/basic_type_mapping.rb +0 -522
  115. data/lib/pg/binary_decoder.rb +0 -23
  116. data/lib/pg/constants.rb +0 -12
  117. data/lib/pg/text_decoder.rb +0 -46
  118. data/lib/pg/text_encoder.rb +0 -59
  119. data/spec/data/expected_trace.out +0 -26
  120. data/spec/data/random_binary_data +0 -0
  121. data/spec/helpers.rb +0 -380
  122. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  123. data/spec/pg/connection_spec.rb +0 -1949
  124. data/spec/pg/connection_sync_spec.rb +0 -41
  125. data/spec/pg/result_spec.rb +0 -681
  126. data/spec/pg/tuple_spec.rb +0 -333
  127. data/spec/pg/type_map_by_class_spec.rb +0 -138
  128. data/spec/pg/type_map_by_column_spec.rb +0 -226
  129. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  130. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  131. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  132. data/spec/pg/type_map_spec.rb +0 -22
  133. data/spec/pg/type_spec.rb +0 -1123
  134. data/spec/pg_spec.rb +0 -50
data/ext/extconf.rb CHANGED
@@ -15,6 +15,13 @@ if pgdir = with_config( 'pg' )
15
15
  ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
16
16
  end
17
17
 
18
+ if enable_config("gvl-unlock", true)
19
+ $defs.push( "-DENABLE_GVL_UNLOCK" )
20
+ $stderr.puts "Calling libpq with GVL unlocked"
21
+ else
22
+ $stderr.puts "Calling libpq with GVL locked"
23
+ end
24
+
18
25
  if enable_config("windows-cross")
19
26
  # Avoid dependency to external libgcc.dll on x86-mingw32
20
27
  $LDFLAGS << " -static-libgcc"
@@ -30,35 +37,101 @@ else
30
37
 
31
38
  if pgconfig && pgconfig != 'ignore'
32
39
  $stderr.puts "Using config values from %s" % [ pgconfig ]
33
- incdir = `"#{pgconfig}" --includedir`.chomp
34
- libdir = `"#{pgconfig}" --libdir`.chomp
40
+ incdir = IO.popen([pgconfig, "--includedir"], &:read).chomp
41
+ libdir = IO.popen([pgconfig, "--libdir"], &:read).chomp
35
42
  dir_config 'pg', incdir, libdir
36
43
 
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}"
44
+ # Windows traditionally stores DLLs beside executables, not in libdir
45
+ dlldir = RUBY_PLATFORM=~/mingw|mswin/ ? IO.popen([pgconfig, "--bindir"], &:read).chomp : libdir
46
+
47
+ elsif checking_for "libpq per pkg-config" do
48
+ _cflags, ldflags, _libs = pkg_config("libpq")
49
+ dlldir = ldflags && ldflags[/-L([^ ]+)/] && $1
42
50
  end
51
+
43
52
  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'
53
+ incdir, libdir = dir_config 'pg'
54
+ dlldir = libdir
47
55
  end
56
+
57
+ # Try to use runtime path linker option, even if RbConfig doesn't know about it.
58
+ # The rpath option is usually set implicit by dir_config(), but so far not
59
+ # on MacOS-X.
60
+ if dlldir && RbConfig::CONFIG["RPATHFLAG"].to_s.empty?
61
+ append_ldflags "-Wl,-rpath,#{dlldir.quote}"
62
+ end
63
+
64
+ if /mswin/ =~ RUBY_PLATFORM
65
+ $libs = append_library($libs, 'ws2_32')
66
+ end
67
+ end
68
+
69
+ $stderr.puts "Using libpq from #{dlldir}"
70
+
71
+ File.write("postgresql_lib_path.rb", <<-EOT)
72
+ module PG
73
+ POSTGRESQL_LIB_PATH = #{dlldir.inspect}
48
74
  end
75
+ EOT
76
+ $INSTALLFILES = {
77
+ "./postgresql_lib_path.rb" => "$(RUBYLIBDIR)/pg/"
78
+ }
49
79
 
50
80
  if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
51
81
  append_cppflags( '-D__EXTENSIONS__' )
52
82
  end
53
83
 
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"
84
+ begin
85
+ find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
86
+ find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
87
+ find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
88
+
89
+ abort "Can't find the PostgreSQL client library (libpq)" unless
90
+ have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
91
+ have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
92
+ have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
93
+
94
+ rescue SystemExit
95
+ install_text = case RUBY_PLATFORM
96
+ when /linux/
97
+ <<-EOT
98
+ Please install libpq or postgresql client package like so:
99
+ sudo apt install libpq-dev
100
+ sudo yum install postgresql-devel
101
+ sudo zypper in postgresql-devel
102
+ sudo pacman -S postgresql-libs
103
+ EOT
104
+ when /darwin/
105
+ <<-EOT
106
+ Please install libpq or postgresql client package like so:
107
+ brew install libpq
108
+ EOT
109
+ when /mingw/
110
+ <<-EOT
111
+ Please install libpq or postgresql client package like so:
112
+ ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
113
+ EOT
114
+ else
115
+ <<-EOT
116
+ Please install libpq or postgresql client package.
117
+ EOT
118
+ end
119
+
120
+ $stderr.puts <<-EOT
121
+ *****************************************************************************
122
+
123
+ Unable to find PostgreSQL client library.
124
+
125
+ #{install_text}
126
+ or try again with:
127
+ gem install pg -- --with-pg-config=/path/to/pg_config
57
128
 
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'] )
129
+ or set library paths manually with:
130
+ gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/
131
+
132
+ EOT
133
+ raise
134
+ end
62
135
 
63
136
  if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
64
137
  # Work around: https://sourceware.org/bugzilla/show_bug.cgi?id=22504
@@ -69,21 +142,27 @@ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
69
142
  end
70
143
  end
71
144
 
72
- # optional headers/functions
73
- have_func 'PQsetSingleRowMode' or
145
+ have_func 'PQconninfo', 'libpq-fe.h' or
74
146
  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
147
+ "of this gem or upgrade your database to at least PostgreSQL-9.3."
148
+ # 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
+ have_func 'PQresultMemorySize', 'libpq-fe.h' # since PostgreSQL-12
153
+ have_func 'PQenterPipelineMode', 'libpq-fe.h' do |src| # since PostgreSQL-14
154
+ # Ensure header files fit as well
155
+ src + " int con(){ return PGRES_PIPELINE_SYNC; }"
156
+ end
81
157
  have_func 'timegm'
82
158
  have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
159
+ have_func 'rb_gc_mark_movable' # since ruby-2.7
160
+ have_func 'rb_io_wait' # since ruby-3.0
83
161
 
84
162
  # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
85
163
  have_header 'unistd.h'
86
164
  have_header 'inttypes.h'
165
+ have_header('ruby/fiber/scheduler.h') if RUBY_PLATFORM=~/mingw|mswin/
87
166
 
88
167
  checking_for "C99 variable length arrays" do
89
168
  $defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
data/ext/gvl_wrappers.c CHANGED
@@ -9,9 +9,13 @@
9
9
  char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm){return NULL;}
10
10
  #endif
11
11
 
12
+ #ifdef ENABLE_GVL_UNLOCK
12
13
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
13
14
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
15
+ #endif
14
16
  FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
17
+ #ifdef ENABLE_GVL_UNLOCK
15
18
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
16
19
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
20
+ #endif
17
21
  FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
data/ext/gvl_wrappers.h CHANGED
@@ -17,6 +17,10 @@
17
17
 
18
18
  #include <ruby/thread.h>
19
19
 
20
+ #ifdef RUBY_EXTCONF_H
21
+ # include RUBY_EXTCONF_H
22
+ #endif
23
+
20
24
  #define DEFINE_PARAM_LIST1(type, name) \
21
25
  name,
22
26
 
@@ -46,6 +50,7 @@
46
50
  return NULL; \
47
51
  }
48
52
 
53
+ #ifdef ENABLE_GVL_UNLOCK
49
54
  #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
50
55
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
51
56
  struct gvl_wrapper_##name##_params params = { \
@@ -54,6 +59,13 @@
54
59
  rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, RUBY_UBF_IO, 0); \
55
60
  when_non_void( return params.retval; ) \
56
61
  }
62
+ #else
63
+ #define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
64
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
65
+ when_non_void( return ) \
66
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
67
+ }
68
+ #endif
57
69
 
58
70
  #define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
59
71
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
@@ -66,6 +78,7 @@
66
78
  return NULL; \
67
79
  }
68
80
 
81
+ #ifdef ENABLE_GVL_UNLOCK
69
82
  #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
70
83
  rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
71
84
  struct gvl_wrapper_##name##_params params = { \
@@ -74,6 +87,13 @@
74
87
  rb_thread_call_with_gvl(gvl_##name##_skeleton, &params); \
75
88
  when_non_void( return params.retval; ) \
76
89
  }
90
+ #else
91
+ #define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
92
+ rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
93
+ when_non_void( return ) \
94
+ name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
95
+ }
96
+ #endif
77
97
 
78
98
  #define GVL_TYPE_VOID(string)
79
99
  #define GVL_TYPE_NONVOID(string) string
@@ -95,6 +115,8 @@
95
115
 
96
116
  #define FOR_EACH_PARAM_OF_PQresetPoll(param)
97
117
 
118
+ #define FOR_EACH_PARAM_OF_PQping(param)
119
+
98
120
  #define FOR_EACH_PARAM_OF_PQexec(param) \
99
121
  param(PGconn *, conn)
100
122
 
@@ -196,6 +218,7 @@
196
218
  function(PQreset, GVL_TYPE_VOID, void, PGconn *, conn) \
197
219
  function(PQresetStart, GVL_TYPE_NONVOID, int, PGconn *, conn) \
198
220
  function(PQresetPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
221
+ function(PQping, GVL_TYPE_NONVOID, PGPing, const char *, conninfo) \
199
222
  function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
200
223
  function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
201
224
  function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
data/ext/pg.c CHANGED
@@ -33,7 +33,6 @@
33
33
  *
34
34
  * - PQfreemem -- unnecessary: copied to ruby object, then freed. Ruby object's
35
35
  * memory is freed when it is garbage collected.
36
- * - PQbinaryTuples -- better to use PQfformat
37
36
  * - PQprint -- not very useful
38
37
  * - PQsetdb -- not very useful
39
38
  * - PQoidStatus -- deprecated, use PQoidValue
@@ -74,6 +73,7 @@ VALUE rb_mPGconstants;
74
73
  * The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
75
74
  */
76
75
  const char * const (pg_enc_pg2ruby_mapping[][2]) = {
76
+ {"UTF8", "UTF-8" },
77
77
  {"BIG5", "Big5" },
78
78
  {"EUC_CN", "GB2312" },
79
79
  {"EUC_JP", "EUC-JP" },
@@ -105,7 +105,6 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
105
105
  {"SHIFT_JIS_2004","Windows-31J" },
106
106
  /* {"SQL_ASCII", NULL }, special case*/
107
107
  {"UHC", "CP949" },
108
- {"UTF8", "UTF-8" },
109
108
  {"WIN866", "IBM866" },
110
109
  {"WIN874", "Windows-874" },
111
110
  {"WIN1250", "Windows-1250"},
@@ -120,56 +119,17 @@ const char * const (pg_enc_pg2ruby_mapping[][2]) = {
120
119
  };
121
120
 
122
121
 
123
- /*
124
- * A cache of mapping from PostgreSQL's encoding indices to Ruby's rb_encoding*s.
125
- */
126
- static struct st_table *enc_pg2ruby;
127
-
128
-
129
- /*
130
- * Look up the JOHAB encoding, creating it as a dummy encoding if it's not
131
- * already defined.
132
- */
133
- static rb_encoding *
134
- pg_find_or_create_johab(void)
135
- {
136
- static const char * const aliases[] = { "JOHAB", "Windows-1361", "CP1361" };
137
- int enc_index;
138
- size_t i;
139
-
140
- for (i = 0; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
141
- enc_index = rb_enc_find_index(aliases[i]);
142
- if (enc_index > 0) return rb_enc_from_index(enc_index);
143
- }
144
-
145
- enc_index = rb_define_dummy_encoding(aliases[0]);
146
- return rb_enc_from_index(enc_index);
147
- }
148
-
149
122
  /*
150
123
  * Return the given PostgreSQL encoding ID as an rb_encoding.
151
124
  *
152
125
  * - returns NULL if the client encoding is 'SQL_ASCII'.
153
126
  * - returns ASCII-8BIT if the client encoding is unknown.
154
127
  */
155
- rb_encoding *
128
+ static rb_encoding *
156
129
  pg_get_pg_encoding_as_rb_encoding( int enc_id )
157
130
  {
158
- rb_encoding *enc;
159
-
160
- /* Use the cached value if it exists */
161
- if ( st_lookup(enc_pg2ruby, (st_data_t)enc_id, (st_data_t*)&enc) ) {
162
- return enc;
163
- }
164
- else {
165
- const char *name = pg_encoding_to_char( enc_id );
166
-
167
- enc = pg_get_pg_encname_as_rb_encoding( name );
168
- st_insert( enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc );
169
-
170
- return enc;
171
- }
172
-
131
+ const char *name = pg_encoding_to_char( enc_id );
132
+ return pg_get_pg_encname_as_rb_encoding( name );
173
133
  }
174
134
 
175
135
  /*
@@ -186,10 +146,6 @@ pg_get_pg_encname_as_rb_encoding( const char *pg_encname )
186
146
  return rb_enc_find( pg_enc_pg2ruby_mapping[i][1] );
187
147
  }
188
148
 
189
- /* JOHAB isn't a builtin encoding, so make up a dummy encoding if it's seen */
190
- if ( strncmp(pg_encname, "JOHAB", 5) == 0 )
191
- return pg_find_or_create_johab();
192
-
193
149
  /* Fallthrough to ASCII-8BIT */
194
150
  return rb_ascii8bit_encoding();
195
151
  }
@@ -376,8 +332,13 @@ pg_s_init_ssl(VALUE self, VALUE do_ssl)
376
332
  **************************************************************************/
377
333
 
378
334
  void
379
- Init_pg_ext()
335
+ Init_pg_ext(void)
380
336
  {
337
+
338
+ #ifdef HAVE_RB_EXT_RACTOR_SAFE
339
+ rb_ext_ractor_safe(PQisthreadsafe());
340
+ #endif
341
+
381
342
  if( RTEST(rb_eval_string("ENV['PG_SKIP_DEPRECATION_WARNING']")) ){
382
343
  /* Set all bits to disable all deprecation warnings. */
383
344
  pg_skip_deprecation_warning = 0xFFFF;
@@ -396,8 +357,8 @@ Init_pg_ext()
396
357
  SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
397
358
  SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
398
359
 
399
- rb_define_singleton_method( rb_mPG, "init_openssl", pg_s_init_openssl, 2 );
400
- rb_define_singleton_method( rb_mPG, "init_ssl", pg_s_init_ssl, 1 );
360
+ rb_define_singleton_method( rb_mPG, "init_openssl", pg_s_init_openssl, 2 );
361
+ rb_define_singleton_method( rb_mPG, "init_ssl", pg_s_init_ssl, 1 );
401
362
 
402
363
 
403
364
  /****** PG::Connection CLASS CONSTANTS: Connection Status ******/
@@ -415,14 +376,34 @@ Init_pg_ext()
415
376
  rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
416
377
  /* Waiting for a response from the server. */
417
378
  rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
418
- /* Received authentication; waiting for backend start-up to finish. */
379
+ /* Received authentication; waiting for backend startup. */
419
380
  rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
381
+ /* This state is no longer used. */
382
+ rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
420
383
  /* Negotiating SSL encryption. */
421
384
  rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
422
- /* Negotiating environment-driven parameter settings. */
423
- rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
424
385
  /* Internal state - PG.connect() needed. */
425
386
  rb_define_const(rb_mPGconstants, "CONNECTION_NEEDED", INT2FIX(CONNECTION_NEEDED));
387
+ #if PG_MAJORVERSION_NUM >= 10
388
+ /* Checking if session is read-write. Available since PostgreSQL-10. */
389
+ rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_WRITABLE", INT2FIX(CONNECTION_CHECK_WRITABLE));
390
+ #endif
391
+ #if PG_MAJORVERSION_NUM >= 10
392
+ /* Consuming any extra messages. Available since PostgreSQL-10. */
393
+ rb_define_const(rb_mPGconstants, "CONNECTION_CONSUME", INT2FIX(CONNECTION_CONSUME));
394
+ #endif
395
+ #if PG_MAJORVERSION_NUM >= 12
396
+ /* Negotiating GSSAPI. Available since PostgreSQL-12. */
397
+ rb_define_const(rb_mPGconstants, "CONNECTION_GSS_STARTUP", INT2FIX(CONNECTION_GSS_STARTUP));
398
+ #endif
399
+ #if PG_MAJORVERSION_NUM >= 13
400
+ /* Checking target server properties. Available since PostgreSQL-13. */
401
+ rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_TARGET", INT2FIX(CONNECTION_CHECK_TARGET));
402
+ #endif
403
+ #if PG_MAJORVERSION_NUM >= 14
404
+ /* Checking if server is in standby mode. Available since PostgreSQL-14. */
405
+ rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_STANDBY", INT2FIX(CONNECTION_CHECK_STANDBY));
406
+ #endif
426
407
 
427
408
  /****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
428
409
 
@@ -526,6 +507,19 @@ Init_pg_ext()
526
507
  /* Result#result_status constant - Single tuple from larger resultset. */
527
508
  rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
528
509
 
510
+ #ifdef HAVE_PQENTERPIPELINEMODE
511
+ /* Result#result_status constant - The PG::Result represents a synchronization point in pipeline mode, requested by Connection#pipeline_sync.
512
+ *
513
+ * This status occurs only when pipeline mode has been selected. */
514
+ rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_SYNC", INT2FIX(PGRES_PIPELINE_SYNC));
515
+
516
+ /* Result#result_status constant - The PG::Result represents a pipeline that has received an error from the server.
517
+ *
518
+ * Connection#get_result must be called repeatedly, and each time it will return this status code until the end of the current pipeline, at which point it will return PG::PGRES_PIPELINE_SYNC and normal processing can resume.
519
+ */
520
+ rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_ABORTED", INT2FIX(PGRES_PIPELINE_ABORTED));
521
+ #endif
522
+
529
523
  /****** Result CONSTANTS: result error field codes ******/
530
524
 
531
525
  /* Result#result_error_field argument constant
@@ -549,7 +543,7 @@ Init_pg_ext()
549
543
  /* Result#result_error_field argument constant
550
544
  *
551
545
  * The SQLSTATE code for the error.
552
- * The SQLSTATE code identies the type of error that has occurred; it can be used by front-end applications to perform specic operations (such as error handling) in response to a particular database 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.
553
547
  * For a list of the possible SQLSTATE codes, see Appendix A.
554
548
  * This field is not localizable, and is always present.
555
549
  */
@@ -645,15 +639,37 @@ Init_pg_ext()
645
639
  rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
646
640
  #endif
647
641
 
642
+ #ifdef HAVE_PQENTERPIPELINEMODE
643
+ /* Connection#pipeline_status constant
644
+ *
645
+ * The libpq connection is in pipeline mode.
646
+ */
647
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ON", INT2FIX(PQ_PIPELINE_ON));
648
+
649
+ /* Connection#pipeline_status constant
650
+ *
651
+ * The libpq connection is not in pipeline mode.
652
+ */
653
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_OFF", INT2FIX(PQ_PIPELINE_OFF));
654
+
655
+ /* Connection#pipeline_status constant
656
+ *
657
+ * The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
658
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
659
+ */
660
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ABORTED", INT2FIX(PQ_PIPELINE_ABORTED));
661
+ #endif
662
+
648
663
  /* Invalid OID constant */
649
664
  rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
650
665
  rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
651
666
 
667
+ /* PostgreSQL compiled in default port */
668
+ rb_define_const(rb_mPGconstants, "DEF_PGPORT", INT2FIX(DEF_PGPORT));
669
+
652
670
  /* Add the constants to the toplevel namespace */
653
671
  rb_include_module( rb_mPG, rb_mPGconstants );
654
672
 
655
- enc_pg2ruby = st_init_numtable();
656
-
657
673
  /* Initialize the main extension classes */
658
674
  init_pg_connection();
659
675
  init_pg_result();
@@ -674,4 +690,3 @@ Init_pg_ext()
674
690
  init_pg_recordcoder();
675
691
  init_pg_tuple();
676
692
  }
677
-
data/ext/pg.h CHANGED
@@ -11,6 +11,7 @@
11
11
  #include <sys/types.h>
12
12
  #if !defined(_WIN32)
13
13
  # include <sys/time.h>
14
+ # include <sys/socket.h>
14
15
  #endif
15
16
  #if defined(HAVE_UNISTD_H) && !defined(_WIN32)
16
17
  # include <unistd.h>
@@ -56,6 +57,7 @@
56
57
  #endif
57
58
 
58
59
  /* PostgreSQL headers */
60
+ #include "pg_config.h"
59
61
  #include "libpq-fe.h"
60
62
  #include "libpq/libpq-fs.h" /* large-object interface */
61
63
  #include "pg_config_manual.h"
@@ -74,10 +76,21 @@ typedef long suseconds_t;
74
76
  #define PG_MAX_COLUMNS 4000
75
77
  #endif
76
78
 
77
- #ifndef RARRAY_AREF
78
- #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
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
86
  #endif
80
87
 
88
+ /* For compatibility with ruby < 3.0 */
89
+ #ifndef RUBY_TYPED_FROZEN_SHAREABLE
90
+ #define PG_RUBY_TYPED_FROZEN_SHAREABLE 0
91
+ #else
92
+ #define PG_RUBY_TYPED_FROZEN_SHAREABLE RUBY_TYPED_FROZEN_SHAREABLE
93
+ #endif
81
94
  #define PG_ENC_IDX_BITS 28
82
95
 
83
96
  /* The data behind each PG::Connection object */
@@ -86,6 +99,9 @@ typedef struct {
86
99
 
87
100
  /* Cached IO object for the socket descriptor */
88
101
  VALUE socket_io;
102
+ /* function pointers of the original libpq notice receivers */
103
+ PQnoticeReceiver default_notice_receiver;
104
+ PQnoticeProcessor default_notice_processor;
89
105
  /* Proc object that receives notices as PG::Result objects */
90
106
  VALUE notice_receiver;
91
107
  /* Proc object that receives notices as String objects */
@@ -104,6 +120,8 @@ typedef struct {
104
120
  int enc_idx : PG_ENC_IDX_BITS;
105
121
  /* flags controlling Symbol/String field names */
106
122
  unsigned int flags : 2;
123
+ /* enable automatic flushing of send data at the end of send_query calls */
124
+ unsigned int flush_data : 1;
107
125
 
108
126
  #if defined(_WIN32)
109
127
  /* File descriptor to be used for rb_w32_unwrap_io_handle() */
@@ -220,6 +238,8 @@ typedef struct {
220
238
  } convs[0];
221
239
  } t_tmbc;
222
240
 
241
+ extern const rb_data_type_t pg_typemap_type;
242
+ extern const rb_data_type_t pg_coder_type;
223
243
 
224
244
  #include "gvl_wrappers.h"
225
245
 
@@ -299,12 +319,12 @@ int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, c
299
319
  int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
300
320
  t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
301
321
  t_pg_coder_dec_func pg_coder_dec_func _(( t_pg_coder*, int ));
302
- void pg_define_coder _(( const char *, void *, VALUE, VALUE ));
322
+ VALUE pg_define_coder _(( const char *, void *, VALUE, VALUE ));
303
323
  VALUE pg_obj_to_i _(( VALUE ));
304
324
  VALUE pg_tmbc_allocate _(( void ));
305
325
  void pg_coder_init_encoder _(( VALUE ));
306
326
  void pg_coder_init_decoder _(( VALUE ));
307
- void pg_coder_mark _(( t_pg_coder * ));
327
+ void pg_coder_compact _(( void * ));
308
328
  char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
309
329
 
310
330
  #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
@@ -324,9 +344,13 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
324
344
  VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
325
345
  t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
326
346
  VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
347
+ void pg_typemap_mark _(( void * ));
348
+ size_t pg_typemap_memsize _(( const void * ));
349
+ void pg_typemap_compact _(( void * ));
327
350
 
328
351
  PGconn *pg_get_pgconn _(( VALUE ));
329
352
  t_pg_connection *pg_get_connection _(( VALUE ));
353
+ VALUE pgconn_block _(( int, VALUE *, VALUE ));
330
354
 
331
355
  VALUE pg_new_result _(( PGresult *, VALUE ));
332
356
  VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
@@ -345,7 +369,6 @@ pgresult_get_this( VALUE self )
345
369
  }
346
370
 
347
371
 
348
- rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
349
372
  rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
350
373
  const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
351
374
  rb_encoding *pg_conn_enc_get _(( PGconn * ));