pg 1.2.0-x86-mingw32 → 1.3.0.rc1-x86-mingw32

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 (112) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +80 -0
  6. data/.github/workflows/source-gem.yml +129 -0
  7. data/.gitignore +13 -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 +14 -0
  15. data/History.rdoc +98 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +9 -8
  18. data/Rakefile +31 -140
  19. data/Rakefile.cross +54 -56
  20. data/certs/ged.pem +24 -0
  21. data/ext/errorcodes.def +8 -0
  22. data/ext/errorcodes.txt +3 -1
  23. data/ext/extconf.rb +90 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +35 -1
  27. data/ext/pg.h +18 -0
  28. data/ext/pg_coder.c +90 -24
  29. data/ext/pg_connection.c +538 -279
  30. data/ext/pg_copy_coder.c +45 -15
  31. data/ext/pg_record_coder.c +38 -9
  32. data/ext/pg_result.c +70 -34
  33. data/ext/pg_text_decoder.c +1 -1
  34. data/ext/pg_text_encoder.c +6 -6
  35. data/ext/pg_tuple.c +47 -21
  36. data/ext/pg_type_map.c +41 -8
  37. data/ext/pg_type_map_all_strings.c +14 -1
  38. data/ext/pg_type_map_by_class.c +50 -21
  39. data/ext/pg_type_map_by_column.c +64 -28
  40. data/ext/pg_type_map_by_mri_type.c +47 -18
  41. data/ext/pg_type_map_by_oid.c +52 -23
  42. data/ext/pg_type_map_in_ruby.c +50 -19
  43. data/ext/pg_util.c +2 -2
  44. data/lib/2.5/pg_ext.so +0 -0
  45. data/lib/2.6/pg_ext.so +0 -0
  46. data/lib/2.7/pg_ext.so +0 -0
  47. data/lib/3.0/pg_ext.so +0 -0
  48. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  49. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  50. data/lib/pg/basic_type_map_for_results.rb +81 -0
  51. data/lib/pg/basic_type_registry.rb +296 -0
  52. data/lib/pg/coder.rb +1 -1
  53. data/lib/pg/connection.rb +369 -56
  54. data/lib/pg/version.rb +4 -0
  55. data/lib/pg.rb +38 -24
  56. data/lib/x86-mingw32/libpq.dll +0 -0
  57. data/misc/openssl-pg-segfault.rb +31 -0
  58. data/misc/postgres/History.txt +9 -0
  59. data/misc/postgres/Manifest.txt +5 -0
  60. data/misc/postgres/README.txt +21 -0
  61. data/misc/postgres/Rakefile +21 -0
  62. data/misc/postgres/lib/postgres.rb +16 -0
  63. data/misc/ruby-pg/History.txt +9 -0
  64. data/misc/ruby-pg/Manifest.txt +5 -0
  65. data/misc/ruby-pg/README.txt +21 -0
  66. data/misc/ruby-pg/Rakefile +21 -0
  67. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  68. data/pg.gemspec +32 -0
  69. data/sample/array_insert.rb +20 -0
  70. data/sample/async_api.rb +106 -0
  71. data/sample/async_copyto.rb +39 -0
  72. data/sample/async_mixed.rb +56 -0
  73. data/sample/check_conn.rb +21 -0
  74. data/sample/copydata.rb +71 -0
  75. data/sample/copyfrom.rb +81 -0
  76. data/sample/copyto.rb +19 -0
  77. data/sample/cursor.rb +21 -0
  78. data/sample/disk_usage_report.rb +177 -0
  79. data/sample/issue-119.rb +94 -0
  80. data/sample/losample.rb +69 -0
  81. data/sample/minimal-testcase.rb +17 -0
  82. data/sample/notify_wait.rb +72 -0
  83. data/sample/pg_statistics.rb +285 -0
  84. data/sample/replication_monitor.rb +222 -0
  85. data/sample/test_binary_values.rb +33 -0
  86. data/sample/wal_shipper.rb +434 -0
  87. data/sample/warehouse_partitions.rb +311 -0
  88. data.tar.gz.sig +0 -0
  89. metadata +83 -232
  90. metadata.gz.sig +0 -0
  91. data/ChangeLog +0 -0
  92. data/lib/2.2/pg_ext.so +0 -0
  93. data/lib/2.3/pg_ext.so +0 -0
  94. data/lib/2.4/pg_ext.so +0 -0
  95. data/lib/libpq.dll +0 -0
  96. data/lib/pg/basic_type_mapping.rb +0 -522
  97. data/spec/data/expected_trace.out +0 -26
  98. data/spec/data/random_binary_data +0 -0
  99. data/spec/helpers.rb +0 -382
  100. data/spec/pg/basic_type_mapping_spec.rb +0 -645
  101. data/spec/pg/connection_spec.rb +0 -1911
  102. data/spec/pg/connection_sync_spec.rb +0 -41
  103. data/spec/pg/result_spec.rb +0 -681
  104. data/spec/pg/tuple_spec.rb +0 -333
  105. data/spec/pg/type_map_by_class_spec.rb +0 -138
  106. data/spec/pg/type_map_by_column_spec.rb +0 -226
  107. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  108. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  109. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  110. data/spec/pg/type_map_spec.rb +0 -22
  111. data/spec/pg/type_spec.rb +0 -1123
  112. 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"
@@ -34,31 +41,93 @@ else
34
41
  libdir = `"#{pgconfig}" --libdir`.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/ ? `"#{pgconfig}" --bindir`.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
+ end
64
+
65
+ $stderr.puts "Using libpq from #{dlldir}"
66
+
67
+ File.write("postgresql_lib_path.rb", <<-EOT)
68
+ module PG
69
+ POSTGRESQL_LIB_PATH = #{dlldir.inspect}
48
70
  end
71
+ EOT
72
+ $INSTALLFILES = {
73
+ "./postgresql_lib_path.rb" => "$(RUBYLIBDIR)/pg/"
74
+ }
49
75
 
50
76
  if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
51
77
  append_cppflags( '-D__EXTENSIONS__' )
52
78
  end
53
79
 
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"
80
+ begin
81
+ find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
82
+ find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
83
+ find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
84
+
85
+ abort "Can't find the PostgreSQL client library (libpq)" unless
86
+ have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
87
+ have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
88
+ have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
89
+
90
+ rescue SystemExit => err
91
+ install_text = case RUBY_PLATFORM
92
+ when /linux/
93
+ <<-EOT
94
+ Please install libpq or postgresql client package like so:
95
+ sudo apt install libpq-dev
96
+ sudo yum install postgresql-devel
97
+ sudo zypper in postgresql-devel
98
+ sudo pacman -S postgresql-libs
99
+ EOT
100
+ when /darwin/
101
+ <<-EOT
102
+ Please install libpq or postgresql client package like so:
103
+ brew install libpq
104
+ EOT
105
+ when /mingw/
106
+ <<-EOT
107
+ Please install libpq or postgresql client package like so:
108
+ ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
109
+ EOT
110
+ else
111
+ <<-EOT
112
+ Please install libpq or postgresql client package.
113
+ EOT
114
+ end
115
+
116
+ $stderr.puts <<-EOT
117
+ *****************************************************************************
118
+
119
+ Unable to find PostgreSQL client library.
120
+
121
+ #{install_text}
122
+ or try again with:
123
+ gem install pg -- --with-pg-config=/path/to/pg_config
57
124
 
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'] )
125
+ or set library paths manually with:
126
+ gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/
127
+
128
+ EOT
129
+ raise
130
+ end
62
131
 
63
132
  if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
64
133
  # Work around: https://sourceware.org/bugzilla/show_bug.cgi?id=22504
@@ -69,17 +138,19 @@ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
69
138
  end
70
139
  end
71
140
 
72
- # optional headers/functions
73
- have_func 'PQsetSingleRowMode' or
141
+ have_func 'PQconninfo' or
74
142
  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
143
+ "of this gem or upgrade your database to at least PostgreSQL-9.3."
144
+ # optional headers/functions
77
145
  have_func 'PQsslAttribute' # since PostgreSQL-9.5
78
146
  have_func 'PQresultVerboseErrorMessage' # since PostgreSQL-9.6
79
147
  have_func 'PQencryptPasswordConn' # since PostgreSQL-10
80
148
  have_func 'PQresultMemorySize' # since PostgreSQL-12
149
+ have_func 'PQenterPipelineMode' # since PostgreSQL-14
81
150
  have_func 'timegm'
82
151
  have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
152
+ have_func 'rb_gc_mark_movable' # since ruby-2.7
153
+ have_func 'rb_io_wait' # since ruby-3.0
83
154
 
84
155
  # unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
85
156
  have_header 'unistd.h'
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
@@ -526,6 +526,19 @@ Init_pg_ext()
526
526
  /* Result#result_status constant - Single tuple from larger resultset. */
527
527
  rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
528
528
 
529
+ #ifdef HAVE_PQENTERPIPELINEMODE
530
+ /* Result#result_status constant - The PG::Result represents a synchronization point in pipeline mode, requested by Connection#pipeline_sync.
531
+ *
532
+ * This status occurs only when pipeline mode has been selected. */
533
+ rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_SYNC", INT2FIX(PGRES_PIPELINE_SYNC));
534
+
535
+ /* Result#result_status constant - The PG::Result represents a pipeline that has received an error from the server.
536
+ *
537
+ * 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.
538
+ */
539
+ rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_ABORTED", INT2FIX(PGRES_PIPELINE_ABORTED));
540
+ #endif
541
+
529
542
  /****** Result CONSTANTS: result error field codes ******/
530
543
 
531
544
  /* Result#result_error_field argument constant
@@ -549,7 +562,7 @@ Init_pg_ext()
549
562
  /* Result#result_error_field argument constant
550
563
  *
551
564
  * 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.
565
+ * 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
566
  * For a list of the possible SQLSTATE codes, see Appendix A.
554
567
  * This field is not localizable, and is always present.
555
568
  */
@@ -645,6 +658,27 @@ Init_pg_ext()
645
658
  rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
646
659
  #endif
647
660
 
661
+ #ifdef HAVE_PQENTERPIPELINEMODE
662
+ /* Connection#pipeline_status constant
663
+ *
664
+ * The libpq connection is in pipeline mode.
665
+ */
666
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ON", INT2FIX(PQ_PIPELINE_ON));
667
+
668
+ /* Connection#pipeline_status constant
669
+ *
670
+ * The libpq connection is not in pipeline mode.
671
+ */
672
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_OFF", INT2FIX(PQ_PIPELINE_OFF));
673
+
674
+ /* Connection#pipeline_status constant
675
+ *
676
+ * The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
677
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
678
+ */
679
+ rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ABORTED", INT2FIX(PQ_PIPELINE_ABORTED));
680
+ #endif
681
+
648
682
  /* Invalid OID constant */
649
683
  rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
650
684
  rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
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>
@@ -78,6 +79,15 @@ typedef long suseconds_t;
78
79
  #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
79
80
  #endif
80
81
 
82
+ #ifdef HAVE_RB_GC_MARK_MOVABLE
83
+ #define pg_compact_callback(x) (x)
84
+ #define pg_gc_location(x) x = rb_gc_location(x)
85
+ #else
86
+ #define rb_gc_mark_movable(x) rb_gc_mark(x)
87
+ #define pg_compact_callback(x) {(x)}
88
+ #define pg_gc_location(x) UNUSED(x)
89
+ #endif
90
+
81
91
  #define PG_ENC_IDX_BITS 28
82
92
 
83
93
  /* The data behind each PG::Connection object */
@@ -104,6 +114,8 @@ typedef struct {
104
114
  int enc_idx : PG_ENC_IDX_BITS;
105
115
  /* flags controlling Symbol/String field names */
106
116
  unsigned int flags : 2;
117
+ /* enable automatic flushing of send data at the end of send_query calls */
118
+ unsigned int flush_data : 1;
107
119
 
108
120
  #if defined(_WIN32)
109
121
  /* File descriptor to be used for rb_w32_unwrap_io_handle() */
@@ -220,6 +232,8 @@ typedef struct {
220
232
  } convs[0];
221
233
  } t_tmbc;
222
234
 
235
+ extern const rb_data_type_t pg_typemap_type;
236
+ extern const rb_data_type_t pg_coder_type;
223
237
 
224
238
  #include "gvl_wrappers.h"
225
239
 
@@ -304,6 +318,7 @@ VALUE pg_obj_to_i _(( VALUE ));
304
318
  VALUE pg_tmbc_allocate _(( void ));
305
319
  void pg_coder_init_encoder _(( VALUE ));
306
320
  void pg_coder_init_decoder _(( VALUE ));
321
+ void pg_coder_compact _(( void * ));
307
322
  char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
308
323
 
309
324
  #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
@@ -323,6 +338,9 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
323
338
  VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
324
339
  t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
325
340
  VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
341
+ void pg_typemap_mark _(( void * ));
342
+ size_t pg_typemap_memsize _(( const void * ));
343
+ void pg_typemap_compact _(( void * ));
326
344
 
327
345
  PGconn *pg_get_pgconn _(( VALUE ));
328
346
  t_pg_connection *pg_get_connection _(( VALUE ));
data/ext/pg_coder.c CHANGED
@@ -26,11 +26,11 @@ pg_coder_allocate( VALUE klass )
26
26
  void
27
27
  pg_coder_init_encoder( VALUE self )
28
28
  {
29
- t_pg_coder *this = DATA_PTR( self );
29
+ t_pg_coder *this = RTYPEDDATA_DATA( self );
30
30
  VALUE klass = rb_class_of(self);
31
31
  if( rb_const_defined( klass, s_id_CFUNC ) ){
32
32
  VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
33
- this->enc_func = DATA_PTR(cfunc);
33
+ this->enc_func = RTYPEDDATA_DATA(cfunc);
34
34
  } else {
35
35
  this->enc_func = NULL;
36
36
  }
@@ -45,12 +45,12 @@ pg_coder_init_encoder( VALUE self )
45
45
  void
46
46
  pg_coder_init_decoder( VALUE self )
47
47
  {
48
- t_pg_coder *this = DATA_PTR( self );
48
+ t_pg_coder *this = RTYPEDDATA_DATA( self );
49
49
  VALUE klass = rb_class_of(self);
50
50
  this->enc_func = NULL;
51
51
  if( rb_const_defined( klass, s_id_CFUNC ) ){
52
52
  VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
53
- this->dec_func = DATA_PTR(cfunc);
53
+ this->dec_func = RTYPEDDATA_DATA(cfunc);
54
54
  } else {
55
55
  this->dec_func = NULL;
56
56
  }
@@ -61,20 +61,74 @@ pg_coder_init_decoder( VALUE self )
61
61
  rb_iv_set( self, "@name", Qnil );
62
62
  }
63
63
 
64
+ static size_t
65
+ pg_coder_memsize(const void *_this)
66
+ {
67
+ const t_pg_coder *this = (const t_pg_coder *)_this;
68
+ return sizeof(*this);
69
+ }
70
+
71
+ static size_t
72
+ pg_composite_coder_memsize(const void *_this)
73
+ {
74
+ const t_pg_composite_coder *this = (const t_pg_composite_coder *)_this;
75
+ return sizeof(*this);
76
+ }
77
+
78
+ void
79
+ pg_coder_compact(void *_this)
80
+ {
81
+ t_pg_coder *this = (t_pg_coder *)_this;
82
+ pg_gc_location(this->coder_obj);
83
+ }
84
+
85
+ static void
86
+ pg_composite_coder_compact(void *_this)
87
+ {
88
+ t_pg_composite_coder *this = (t_pg_composite_coder *)_this;
89
+ pg_coder_compact(&this->comp);
90
+ }
91
+
92
+ const rb_data_type_t pg_coder_type = {
93
+ "PG::Coder",
94
+ {
95
+ (RUBY_DATA_FUNC) NULL,
96
+ RUBY_TYPED_DEFAULT_FREE,
97
+ pg_coder_memsize,
98
+ pg_compact_callback(pg_coder_compact),
99
+ },
100
+ 0,
101
+ 0,
102
+ RUBY_TYPED_FREE_IMMEDIATELY,
103
+ };
104
+
64
105
  static VALUE
65
106
  pg_simple_encoder_allocate( VALUE klass )
66
107
  {
67
108
  t_pg_coder *this;
68
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
109
+ VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
69
110
  pg_coder_init_encoder( self );
70
111
  return self;
71
112
  }
72
113
 
114
+ static const rb_data_type_t pg_composite_coder_type = {
115
+ "PG::CompositeCoder",
116
+ {
117
+ (RUBY_DATA_FUNC) NULL,
118
+ RUBY_TYPED_DEFAULT_FREE,
119
+ pg_composite_coder_memsize,
120
+ pg_compact_callback(pg_composite_coder_compact),
121
+ },
122
+ &pg_coder_type,
123
+ 0,
124
+ RUBY_TYPED_FREE_IMMEDIATELY,
125
+ };
126
+
73
127
  static VALUE
74
128
  pg_composite_encoder_allocate( VALUE klass )
75
129
  {
76
130
  t_pg_composite_coder *this;
77
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
131
+ VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
78
132
  pg_coder_init_encoder( self );
79
133
  this->elem = NULL;
80
134
  this->needs_quotation = 1;
@@ -87,7 +141,7 @@ static VALUE
87
141
  pg_simple_decoder_allocate( VALUE klass )
88
142
  {
89
143
  t_pg_coder *this;
90
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
144
+ VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
91
145
  pg_coder_init_decoder( self );
92
146
  return self;
93
147
  }
@@ -96,7 +150,7 @@ static VALUE
96
150
  pg_composite_decoder_allocate( VALUE klass )
97
151
  {
98
152
  t_pg_composite_coder *this;
99
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
153
+ VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
100
154
  pg_coder_init_decoder( self );
101
155
  this->elem = NULL;
102
156
  this->needs_quotation = 1;
@@ -123,7 +177,7 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
123
177
  VALUE value;
124
178
  int len, len2;
125
179
  int enc_idx;
126
- t_pg_coder *this = DATA_PTR(self);
180
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
127
181
 
128
182
  if(argc < 1 || argc > 2){
129
183
  rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
@@ -180,7 +234,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
180
234
  int tuple = -1;
181
235
  int field = -1;
182
236
  VALUE res;
183
- t_pg_coder *this = DATA_PTR(self);
237
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
184
238
 
185
239
  if(argc < 1 || argc > 3){
186
240
  rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
@@ -201,7 +255,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
201
255
  rb_raise(rb_eRuntimeError, "no decoder function defined");
202
256
  }
203
257
 
204
- res = this->dec_func(this, val, RSTRING_LEN(argv[0]), tuple, field, ENCODING_GET(argv[0]));
258
+ res = this->dec_func(this, val, RSTRING_LENINT(argv[0]), tuple, field, ENCODING_GET(argv[0]));
205
259
 
206
260
  return res;
207
261
  }
@@ -218,7 +272,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
218
272
  static VALUE
219
273
  pg_coder_oid_set(VALUE self, VALUE oid)
220
274
  {
221
- t_pg_coder *this = DATA_PTR(self);
275
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
222
276
  this->oid = NUM2UINT(oid);
223
277
  return oid;
224
278
  }
@@ -233,7 +287,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
233
287
  static VALUE
234
288
  pg_coder_oid_get(VALUE self)
235
289
  {
236
- t_pg_coder *this = DATA_PTR(self);
290
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
237
291
  return UINT2NUM(this->oid);
238
292
  }
239
293
 
@@ -249,7 +303,7 @@ pg_coder_oid_get(VALUE self)
249
303
  static VALUE
250
304
  pg_coder_format_set(VALUE self, VALUE format)
251
305
  {
252
- t_pg_coder *this = DATA_PTR(self);
306
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
253
307
  this->format = NUM2INT(format);
254
308
  return format;
255
309
  }
@@ -264,7 +318,7 @@ pg_coder_format_set(VALUE self, VALUE format)
264
318
  static VALUE
265
319
  pg_coder_format_get(VALUE self)
266
320
  {
267
- t_pg_coder *this = DATA_PTR(self);
321
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
268
322
  return INT2NUM(this->format);
269
323
  }
270
324
 
@@ -280,7 +334,7 @@ pg_coder_format_get(VALUE self)
280
334
  static VALUE
281
335
  pg_coder_flags_set(VALUE self, VALUE flags)
282
336
  {
283
- t_pg_coder *this = DATA_PTR(self);
337
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
284
338
  this->flags = NUM2INT(flags);
285
339
  return flags;
286
340
  }
@@ -294,7 +348,7 @@ pg_coder_flags_set(VALUE self, VALUE flags)
294
348
  static VALUE
295
349
  pg_coder_flags_get(VALUE self)
296
350
  {
297
- t_pg_coder *this = DATA_PTR(self);
351
+ t_pg_coder *this = RTYPEDDATA_DATA(self);
298
352
  return INT2NUM(this->flags);
299
353
  }
300
354
 
@@ -311,7 +365,7 @@ pg_coder_flags_get(VALUE self)
311
365
  static VALUE
312
366
  pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
313
367
  {
314
- t_pg_composite_coder *this = DATA_PTR(self);
368
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
315
369
  this->needs_quotation = RTEST(needs_quotation);
316
370
  return needs_quotation;
317
371
  }
@@ -326,7 +380,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
326
380
  static VALUE
327
381
  pg_coder_needs_quotation_get(VALUE self)
328
382
  {
329
- t_pg_composite_coder *this = DATA_PTR(self);
383
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
330
384
  return this->needs_quotation ? Qtrue : Qfalse;
331
385
  }
332
386
 
@@ -341,7 +395,7 @@ pg_coder_needs_quotation_get(VALUE self)
341
395
  static VALUE
342
396
  pg_coder_delimiter_set(VALUE self, VALUE delimiter)
343
397
  {
344
- t_pg_composite_coder *this = DATA_PTR(self);
398
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
345
399
  StringValue(delimiter);
346
400
  if(RSTRING_LEN(delimiter) != 1)
347
401
  rb_raise( rb_eArgError, "delimiter size must be one byte");
@@ -358,7 +412,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
358
412
  static VALUE
359
413
  pg_coder_delimiter_get(VALUE self)
360
414
  {
361
- t_pg_composite_coder *this = DATA_PTR(self);
415
+ t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
362
416
  return rb_str_new(&this->delimiter, 1);
363
417
  }
364
418
 
@@ -374,12 +428,12 @@ pg_coder_delimiter_get(VALUE self)
374
428
  static VALUE
375
429
  pg_coder_elements_type_set(VALUE self, VALUE elem_type)
376
430
  {
377
- t_pg_composite_coder *this = DATA_PTR( self );
431
+ t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
378
432
 
379
433
  if ( NIL_P(elem_type) ){
380
434
  this->elem = NULL;
381
435
  } else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
382
- this->elem = DATA_PTR( elem_type );
436
+ this->elem = RTYPEDDATA_DATA( elem_type );
383
437
  } else {
384
438
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
385
439
  rb_obj_classname( elem_type ) );
@@ -389,10 +443,22 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
389
443
  return elem_type;
390
444
  }
391
445
 
446
+ static const rb_data_type_t pg_coder_cfunc_type = {
447
+ "PG::Coder::CFUNC",
448
+ {
449
+ (RUBY_DATA_FUNC)NULL,
450
+ (RUBY_DATA_FUNC)NULL,
451
+ (size_t (*)(const void *))NULL,
452
+ },
453
+ 0,
454
+ 0,
455
+ RUBY_TYPED_FREE_IMMEDIATELY,
456
+ };
457
+
392
458
  void
393
459
  pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
394
460
  {
395
- VALUE cfunc_obj = Data_Wrap_Struct( rb_cObject, NULL, NULL, func );
461
+ VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
396
462
  VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
397
463
  if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
398
464
  rb_include_module( coder_klass, rb_mPG_BinaryFormatting );