pg 1.2.3 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) 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 +86 -0
  6. data/.github/workflows/source-gem.yml +130 -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 +95 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +7 -6
  18. data/Rakefile +27 -138
  19. data/Rakefile.cross +6 -5
  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 +91 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +59 -4
  27. data/ext/pg.h +18 -1
  28. data/ext/pg_coder.c +82 -28
  29. data/ext/pg_connection.c +673 -493
  30. data/ext/pg_copy_coder.c +45 -16
  31. data/ext/pg_record_coder.c +39 -11
  32. data/ext/pg_result.c +61 -31
  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 +49 -24
  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/pg/basic_type_map_based_on_result.rb +47 -0
  45. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  46. data/lib/pg/basic_type_map_for_results.rb +81 -0
  47. data/lib/pg/basic_type_registry.rb +296 -0
  48. data/lib/pg/coder.rb +1 -1
  49. data/lib/pg/connection.rb +588 -58
  50. data/lib/pg/version.rb +4 -0
  51. data/lib/pg.rb +47 -32
  52. data/misc/openssl-pg-segfault.rb +31 -0
  53. data/misc/postgres/History.txt +9 -0
  54. data/misc/postgres/Manifest.txt +5 -0
  55. data/misc/postgres/README.txt +21 -0
  56. data/misc/postgres/Rakefile +21 -0
  57. data/misc/postgres/lib/postgres.rb +16 -0
  58. data/misc/ruby-pg/History.txt +9 -0
  59. data/misc/ruby-pg/Manifest.txt +5 -0
  60. data/misc/ruby-pg/README.txt +21 -0
  61. data/misc/ruby-pg/Rakefile +21 -0
  62. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  63. data/pg.gemspec +32 -0
  64. data/sample/array_insert.rb +20 -0
  65. data/sample/async_api.rb +106 -0
  66. data/sample/async_copyto.rb +39 -0
  67. data/sample/async_mixed.rb +56 -0
  68. data/sample/check_conn.rb +21 -0
  69. data/sample/copydata.rb +71 -0
  70. data/sample/copyfrom.rb +81 -0
  71. data/sample/copyto.rb +19 -0
  72. data/sample/cursor.rb +21 -0
  73. data/sample/disk_usage_report.rb +177 -0
  74. data/sample/issue-119.rb +94 -0
  75. data/sample/losample.rb +69 -0
  76. data/sample/minimal-testcase.rb +17 -0
  77. data/sample/notify_wait.rb +72 -0
  78. data/sample/pg_statistics.rb +285 -0
  79. data/sample/replication_monitor.rb +222 -0
  80. data/sample/test_binary_values.rb +33 -0
  81. data/sample/wal_shipper.rb +434 -0
  82. data/sample/warehouse_partitions.rb +311 -0
  83. data.tar.gz.sig +0 -0
  84. metadata +76 -217
  85. metadata.gz.sig +0 -0
  86. data/ChangeLog +0 -0
  87. data/lib/pg/basic_type_mapping.rb +0 -522
  88. data/spec/data/expected_trace.out +0 -26
  89. data/spec/data/random_binary_data +0 -0
  90. data/spec/helpers.rb +0 -380
  91. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  92. data/spec/pg/connection_spec.rb +0 -1949
  93. data/spec/pg/connection_sync_spec.rb +0 -41
  94. data/spec/pg/result_spec.rb +0 -681
  95. data/spec/pg/tuple_spec.rb +0 -333
  96. data/spec/pg/type_map_by_class_spec.rb +0 -138
  97. data/spec/pg/type_map_by_column_spec.rb +0 -226
  98. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  99. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  100. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  101. data/spec/pg/type_map_spec.rb +0 -22
  102. data/spec/pg/type_spec.rb +0 -1123
  103. data/spec/pg_spec.rb +0 -50
data/ext/pg_copy_coder.c CHANGED
@@ -21,18 +21,47 @@ typedef struct {
21
21
 
22
22
 
23
23
  static void
24
- pg_copycoder_mark( t_pg_copycoder *this )
24
+ pg_copycoder_mark( void *_this )
25
25
  {
26
- pg_coder_mark(&this->comp);
27
- rb_gc_mark(this->typemap);
28
- rb_gc_mark(this->null_string);
26
+ t_pg_copycoder *this = (t_pg_copycoder *)_this;
27
+ rb_gc_mark_movable(this->typemap);
28
+ rb_gc_mark_movable(this->null_string);
29
29
  }
30
30
 
31
+ static size_t
32
+ pg_copycoder_memsize( const void *_this )
33
+ {
34
+ const t_pg_copycoder *this = (const t_pg_copycoder *)_this;
35
+ return sizeof(*this);
36
+ }
37
+
38
+ static void
39
+ pg_copycoder_compact( void *_this )
40
+ {
41
+ t_pg_copycoder *this = (t_pg_copycoder *)_this;
42
+ pg_coder_compact(&this->comp);
43
+ pg_gc_location(this->typemap);
44
+ pg_gc_location(this->null_string);
45
+ }
46
+
47
+ static const rb_data_type_t pg_copycoder_type = {
48
+ "PG::CopyCoder",
49
+ {
50
+ pg_copycoder_mark,
51
+ RUBY_TYPED_DEFAULT_FREE,
52
+ pg_copycoder_memsize,
53
+ pg_compact_callback(pg_copycoder_compact),
54
+ },
55
+ &pg_coder_type,
56
+ 0,
57
+ RUBY_TYPED_FREE_IMMEDIATELY,
58
+ };
59
+
31
60
  static VALUE
32
61
  pg_copycoder_encoder_allocate( VALUE klass )
33
62
  {
34
63
  t_pg_copycoder *this;
35
- VALUE self = Data_Make_Struct( klass, t_pg_copycoder, pg_copycoder_mark, -1, this );
64
+ VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
36
65
  pg_coder_init_encoder( self );
37
66
  this->typemap = pg_typemap_all_strings;
38
67
  this->delimiter = '\t';
@@ -44,7 +73,7 @@ static VALUE
44
73
  pg_copycoder_decoder_allocate( VALUE klass )
45
74
  {
46
75
  t_pg_copycoder *this;
47
- VALUE self = Data_Make_Struct( klass, t_pg_copycoder, pg_copycoder_mark, -1, this );
76
+ VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
48
77
  pg_coder_init_decoder( self );
49
78
  this->typemap = pg_typemap_all_strings;
50
79
  this->delimiter = '\t';
@@ -63,7 +92,7 @@ pg_copycoder_decoder_allocate( VALUE klass )
63
92
  static VALUE
64
93
  pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
65
94
  {
66
- t_pg_copycoder *this = DATA_PTR(self);
95
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
67
96
  StringValue(delimiter);
68
97
  if(RSTRING_LEN(delimiter) != 1)
69
98
  rb_raise( rb_eArgError, "delimiter size must be one byte");
@@ -80,7 +109,7 @@ pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
80
109
  static VALUE
81
110
  pg_copycoder_delimiter_get(VALUE self)
82
111
  {
83
- t_pg_copycoder *this = DATA_PTR(self);
112
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
84
113
  return rb_str_new(&this->delimiter, 1);
85
114
  }
86
115
 
@@ -93,7 +122,7 @@ pg_copycoder_delimiter_get(VALUE self)
93
122
  static VALUE
94
123
  pg_copycoder_null_string_set(VALUE self, VALUE null_string)
95
124
  {
96
- t_pg_copycoder *this = DATA_PTR(self);
125
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
97
126
  StringValue(null_string);
98
127
  this->null_string = null_string;
99
128
  return null_string;
@@ -105,7 +134,7 @@ pg_copycoder_null_string_set(VALUE self, VALUE null_string)
105
134
  static VALUE
106
135
  pg_copycoder_null_string_get(VALUE self)
107
136
  {
108
- t_pg_copycoder *this = DATA_PTR(self);
137
+ t_pg_copycoder *this = RTYPEDDATA_DATA(self);
109
138
  return this->null_string;
110
139
  }
111
140
 
@@ -123,7 +152,7 @@ pg_copycoder_null_string_get(VALUE self)
123
152
  static VALUE
124
153
  pg_copycoder_type_map_set(VALUE self, VALUE type_map)
125
154
  {
126
- t_pg_copycoder *this = DATA_PTR( self );
155
+ t_pg_copycoder *this = RTYPEDDATA_DATA( self );
127
156
 
128
157
  if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
129
158
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
@@ -143,7 +172,7 @@ pg_copycoder_type_map_set(VALUE self, VALUE type_map)
143
172
  static VALUE
144
173
  pg_copycoder_type_map_get(VALUE self)
145
174
  {
146
- t_pg_copycoder *this = DATA_PTR( self );
175
+ t_pg_copycoder *this = RTYPEDDATA_DATA( self );
147
176
 
148
177
  return this->typemap;
149
178
  }
@@ -188,7 +217,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
188
217
  char *current_out;
189
218
  char *end_capa_ptr;
190
219
 
191
- p_typemap = DATA_PTR( this->typemap );
220
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
192
221
  p_typemap->funcs.fit_to_query( this->typemap, value );
193
222
 
194
223
  /* Allocate a new string with embedded capacity and realloc exponential when needed. */
@@ -225,7 +254,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
225
254
 
226
255
  if( strlen == -1 ){
227
256
  /* we can directly use String value in subint */
228
- strlen = RSTRING_LEN(subint);
257
+ strlen = RSTRING_LENINT(subint);
229
258
 
230
259
  /* size of string assuming the worst case, that every character must be escaped. */
231
260
  PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
@@ -376,7 +405,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
376
405
  char *end_capa_ptr;
377
406
  t_typemap *p_typemap;
378
407
 
379
- p_typemap = DATA_PTR( this->typemap );
408
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
380
409
  expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
381
410
 
382
411
  /* The received input string will probably have this->nfields fields. */
@@ -397,7 +426,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
397
426
  int found_delim = 0;
398
427
  const char *start_ptr;
399
428
  const char *end_ptr;
400
- int input_len;
429
+ long input_len;
401
430
 
402
431
  /* Remember start of field on input side */
403
432
  start_ptr = cur_ptr;
@@ -16,17 +16,45 @@ typedef struct {
16
16
 
17
17
 
18
18
  static void
19
- pg_recordcoder_mark( t_pg_recordcoder *this )
19
+ pg_recordcoder_mark( void *_this )
20
20
  {
21
- pg_coder_mark(&this->comp);
22
- rb_gc_mark(this->typemap);
21
+ t_pg_recordcoder *this = (t_pg_recordcoder *)_this;
22
+ rb_gc_mark_movable(this->typemap);
23
23
  }
24
24
 
25
+ static size_t
26
+ pg_recordcoder_memsize( const void *_this )
27
+ {
28
+ const t_pg_recordcoder *this = (const t_pg_recordcoder *)_this;
29
+ return sizeof(*this);
30
+ }
31
+
32
+ static void
33
+ pg_recordcoder_compact( void *_this )
34
+ {
35
+ t_pg_recordcoder *this = (t_pg_recordcoder *)_this;
36
+ pg_coder_compact(&this->comp);
37
+ pg_gc_location(this->typemap);
38
+ }
39
+
40
+ static const rb_data_type_t pg_recordcoder_type = {
41
+ "PG::RecordCoder",
42
+ {
43
+ pg_recordcoder_mark,
44
+ RUBY_TYPED_DEFAULT_FREE,
45
+ pg_recordcoder_memsize,
46
+ pg_compact_callback(pg_recordcoder_compact),
47
+ },
48
+ &pg_coder_type,
49
+ 0,
50
+ RUBY_TYPED_FREE_IMMEDIATELY,
51
+ };
52
+
25
53
  static VALUE
26
54
  pg_recordcoder_encoder_allocate( VALUE klass )
27
55
  {
28
56
  t_pg_recordcoder *this;
29
- VALUE self = Data_Make_Struct( klass, t_pg_recordcoder, pg_recordcoder_mark, -1, this );
57
+ VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
30
58
  pg_coder_init_encoder( self );
31
59
  this->typemap = pg_typemap_all_strings;
32
60
  return self;
@@ -36,7 +64,7 @@ static VALUE
36
64
  pg_recordcoder_decoder_allocate( VALUE klass )
37
65
  {
38
66
  t_pg_recordcoder *this;
39
- VALUE self = Data_Make_Struct( klass, t_pg_recordcoder, pg_recordcoder_mark, -1, this );
67
+ VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
40
68
  pg_coder_init_decoder( self );
41
69
  this->typemap = pg_typemap_all_strings;
42
70
  return self;
@@ -56,7 +84,7 @@ pg_recordcoder_decoder_allocate( VALUE klass )
56
84
  static VALUE
57
85
  pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
58
86
  {
59
- t_pg_recordcoder *this = DATA_PTR( self );
87
+ t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
60
88
 
61
89
  if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
62
90
  rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
@@ -76,7 +104,7 @@ pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
76
104
  static VALUE
77
105
  pg_recordcoder_type_map_get(VALUE self)
78
106
  {
79
- t_pg_recordcoder *this = DATA_PTR( self );
107
+ t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
80
108
 
81
109
  return this->typemap;
82
110
  }
@@ -106,7 +134,7 @@ pg_recordcoder_type_map_get(VALUE self)
106
134
  * tm = PG::TypeMapByColumn.new([PG::TextEncoder::Float.new]*2)
107
135
  * # Use this type map to encode the record:
108
136
  * PG::TextEncoder::Record.new(type_map: tm).encode([1,2])
109
- * # => "(\"1.0000000000000000E+00\",\"2.0000000000000000E+00\")"
137
+ * # => "(\"1.0\",\"2.0\")"
110
138
  *
111
139
  * Records can also be encoded and decoded directly to and from the database.
112
140
  * This avoids intermediate string allocations and is very fast.
@@ -156,7 +184,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
156
184
  char *current_out;
157
185
  char *end_capa_ptr;
158
186
 
159
- p_typemap = DATA_PTR( this->typemap );
187
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
160
188
  p_typemap->funcs.fit_to_query( this->typemap, value );
161
189
 
162
190
  /* Allocate a new string with embedded capacity and realloc exponential when needed. */
@@ -168,7 +196,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
168
196
  for( i=0; i<RARRAY_LEN(value); i++){
169
197
  char *ptr1;
170
198
  char *ptr2;
171
- int strlen;
199
+ long strlen;
172
200
  int backslashs;
173
201
  VALUE subint;
174
202
  VALUE entry;
@@ -358,7 +386,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
358
386
  char *end_capa_ptr;
359
387
  t_typemap *p_typemap;
360
388
 
361
- p_typemap = DATA_PTR( this->typemap );
389
+ p_typemap = RTYPEDDATA_DATA( this->typemap );
362
390
  expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
363
391
 
364
392
  /* The received input string will probably have this->nfields fields. */
data/ext/pg_result.c CHANGED
@@ -107,17 +107,34 @@ pgresult_approx_size(const PGresult *result)
107
107
  * GC Mark function
108
108
  */
109
109
  static void
110
- pgresult_gc_mark( t_pg_result *this )
110
+ pgresult_gc_mark( void *_this )
111
111
  {
112
+ t_pg_result *this = (t_pg_result *)_this;
112
113
  int i;
113
114
 
114
- rb_gc_mark( this->connection );
115
- rb_gc_mark( this->typemap );
116
- rb_gc_mark( this->tuple_hash );
117
- rb_gc_mark( this->field_map );
115
+ rb_gc_mark_movable( this->connection );
116
+ rb_gc_mark_movable( this->typemap );
117
+ rb_gc_mark_movable( this->tuple_hash );
118
+ rb_gc_mark_movable( this->field_map );
118
119
 
119
120
  for( i=0; i < this->nfields; i++ ){
120
- rb_gc_mark( this->fnames[i] );
121
+ rb_gc_mark_movable( this->fnames[i] );
122
+ }
123
+ }
124
+
125
+ static void
126
+ pgresult_gc_compact( void *_this )
127
+ {
128
+ t_pg_result *this = (t_pg_result *)_this;
129
+ int i;
130
+
131
+ pg_gc_location( this->connection );
132
+ pg_gc_location( this->typemap );
133
+ pg_gc_location( this->tuple_hash );
134
+ pg_gc_location( this->field_map );
135
+
136
+ for( i=0; i < this->nfields; i++ ){
137
+ pg_gc_location( this->fnames[i] );
121
138
  }
122
139
  }
123
140
 
@@ -125,8 +142,9 @@ pgresult_gc_mark( t_pg_result *this )
125
142
  * GC Free function
126
143
  */
127
144
  static void
128
- pgresult_clear( t_pg_result *this )
145
+ pgresult_clear( void *_this )
129
146
  {
147
+ t_pg_result *this = (t_pg_result *)_this;
130
148
  if( this->pgresult && !this->autoclear ){
131
149
  PQclear(this->pgresult);
132
150
  #ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
@@ -139,15 +157,17 @@ pgresult_clear( t_pg_result *this )
139
157
  }
140
158
 
141
159
  static void
142
- pgresult_gc_free( t_pg_result *this )
160
+ pgresult_gc_free( void *_this )
143
161
  {
162
+ t_pg_result *this = (t_pg_result *)_this;
144
163
  pgresult_clear( this );
145
164
  xfree(this);
146
165
  }
147
166
 
148
167
  static size_t
149
- pgresult_memsize( t_pg_result *this )
168
+ pgresult_memsize( const void *_this )
150
169
  {
170
+ const t_pg_result *this = (const t_pg_result *)_this;
151
171
  /* Ideally the memory 'this' is pointing to should be taken into account as well.
152
172
  * However we don't want to store two memory sizes in t_pg_result just for reporting by ObjectSpace.memsize_of.
153
173
  */
@@ -155,16 +175,15 @@ pgresult_memsize( t_pg_result *this )
155
175
  }
156
176
 
157
177
  static const rb_data_type_t pgresult_type = {
158
- "pg",
178
+ "PG::Result",
159
179
  {
160
- (void (*)(void*))pgresult_gc_mark,
161
- (void (*)(void*))pgresult_gc_free,
162
- (size_t (*)(const void *))pgresult_memsize,
180
+ pgresult_gc_mark,
181
+ pgresult_gc_free,
182
+ pgresult_memsize,
183
+ pg_compact_callback(pgresult_gc_compact),
163
184
  },
164
185
  0, 0,
165
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
166
186
  RUBY_TYPED_FREE_IMMEDIATELY,
167
- #endif
168
187
  };
169
188
 
170
189
  /* Needed by sequel_pg gem, do not delete */
@@ -191,7 +210,7 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
191
210
  this->pgresult = result;
192
211
  this->connection = rb_pgconn;
193
212
  this->typemap = pg_typemap_all_strings;
194
- this->p_typemap = DATA_PTR( this->typemap );
213
+ this->p_typemap = RTYPEDDATA_DATA( this->typemap );
195
214
  this->nfields = -1;
196
215
  this->tuple_hash = Qnil;
197
216
  this->field_map = Qnil;
@@ -202,11 +221,11 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
202
221
  t_pg_connection *p_conn = pg_get_connection(rb_pgconn);
203
222
  VALUE typemap = p_conn->type_map_for_results;
204
223
  /* Type check is done when assigned to PG::Connection. */
205
- t_typemap *p_typemap = DATA_PTR(typemap);
224
+ t_typemap *p_typemap = RTYPEDDATA_DATA(typemap);
206
225
 
207
226
  this->enc_idx = p_conn->enc_idx;
208
227
  this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
209
- this->p_typemap = DATA_PTR( this->typemap );
228
+ this->p_typemap = RTYPEDDATA_DATA( this->typemap );
210
229
  this->flags = p_conn->flags;
211
230
  } else {
212
231
  this->enc_idx = rb_locale_encindex();
@@ -270,7 +289,11 @@ pg_new_result_autoclear(PGresult *result, VALUE rb_pgconn)
270
289
  * call-seq:
271
290
  * res.check -> nil
272
291
  *
273
- * Raises appropriate exception if PG::Result is in a bad state.
292
+ * Raises appropriate exception if PG::Result is in a bad state, which is:
293
+ * * +PGRES_BAD_RESPONSE+
294
+ * * +PGRES_FATAL_ERROR+
295
+ * * +PGRES_NONFATAL_ERROR+
296
+ * * +PGRES_PIPELINE_ABORTED+
274
297
  */
275
298
  VALUE
276
299
  pg_result_check( VALUE self )
@@ -295,10 +318,16 @@ pg_result_check( VALUE self )
295
318
  case PGRES_SINGLE_TUPLE:
296
319
  case PGRES_EMPTY_QUERY:
297
320
  case PGRES_COMMAND_OK:
321
+ #ifdef HAVE_PQENTERPIPELINEMODE
322
+ case PGRES_PIPELINE_SYNC:
323
+ #endif
298
324
  return self;
299
325
  case PGRES_BAD_RESPONSE:
300
326
  case PGRES_FATAL_ERROR:
301
327
  case PGRES_NONFATAL_ERROR:
328
+ #ifdef HAVE_PQENTERPIPELINEMODE
329
+ case PGRES_PIPELINE_ABORTED:
330
+ #endif
302
331
  error = rb_str_new2( PQresultErrorMessage(this->pgresult) );
303
332
  break;
304
333
  default:
@@ -353,7 +382,7 @@ pg_result_clear(VALUE self)
353
382
  * call-seq:
354
383
  * res.cleared? -> boolean
355
384
  *
356
- * Returns +true+ if the backend result memory has been free'd.
385
+ * Returns +true+ if the backend result memory has been freed.
357
386
  */
358
387
  VALUE
359
388
  pgresult_cleared_p( VALUE self )
@@ -367,7 +396,7 @@ pgresult_cleared_p( VALUE self )
367
396
  * res.autoclear? -> boolean
368
397
  *
369
398
  * Returns +true+ if the underlying C struct will be cleared at the end of a callback.
370
- * This applies only to Result objects received by the block to PG::Cinnection#set_notice_receiver .
399
+ * This applies only to Result objects received by the block to PG::Connection#set_notice_receiver .
371
400
  *
372
401
  * All other Result objects are automatically cleared by the GC when the object is no longer in use or manually by PG::Result#clear .
373
402
  *
@@ -495,6 +524,9 @@ static void pgresult_init_fnames(VALUE self)
495
524
  * * +PGRES_NONFATAL_ERROR+
496
525
  * * +PGRES_FATAL_ERROR+
497
526
  * * +PGRES_COPY_BOTH+
527
+ * * +PGRES_SINGLE_TUPLE+
528
+ * * +PGRES_PIPELINE_SYNC+
529
+ * * +PGRES_PIPELINE_ABORTED+
498
530
  */
499
531
  static VALUE
500
532
  pgresult_result_status(VALUE self)
@@ -506,7 +538,7 @@ pgresult_result_status(VALUE self)
506
538
  * call-seq:
507
539
  * res.res_status( status ) -> String
508
540
  *
509
- * Returns the string representation of status +status+.
541
+ * Returns the string representation of +status+.
510
542
  *
511
543
  */
512
544
  static VALUE
@@ -1003,7 +1035,7 @@ pgresult_cmd_tuples(VALUE self)
1003
1035
  {
1004
1036
  long n;
1005
1037
  n = strtol(PQcmdTuples(pgresult_get(self)),NULL, 10);
1006
- return INT2NUM(n);
1038
+ return LONG2NUM(n);
1007
1039
  }
1008
1040
 
1009
1041
  /*
@@ -1325,14 +1357,11 @@ pgresult_type_map_set(VALUE self, VALUE typemap)
1325
1357
  t_pg_result *this = pgresult_get_this(self);
1326
1358
  t_typemap *p_typemap;
1327
1359
 
1328
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
1329
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1330
- rb_obj_classname( typemap ) );
1331
- }
1332
- Data_Get_Struct(typemap, t_typemap, p_typemap);
1360
+ /* Check type of method param */
1361
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, p_typemap);
1333
1362
 
1334
1363
  this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
1335
- this->p_typemap = DATA_PTR( this->typemap );
1364
+ this->p_typemap = RTYPEDDATA_DATA( this->typemap );
1336
1365
 
1337
1366
  return typemap;
1338
1367
  }
@@ -1531,7 +1560,7 @@ pgresult_stream_each_tuple(VALUE self)
1531
1560
  * It can be set to one of:
1532
1561
  * * +:string+ to use String based field names
1533
1562
  * * +:symbol+ to use Symbol based field names
1534
- * * +:static_symbol+ to use pinned Symbol (can not be garbage collected) - Don't use this, it will probably removed in future.
1563
+ * * +:static_symbol+ to use pinned Symbol (can not be garbage collected) - Don't use this, it will probably be removed in future.
1535
1564
  *
1536
1565
  * The default is retrieved from PG::Connection#field_name_type , which defaults to +:string+ .
1537
1566
  *
@@ -1587,7 +1616,8 @@ init_pg_result()
1587
1616
  sym_symbol = ID2SYM(rb_intern("symbol"));
1588
1617
  sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
1589
1618
 
1590
- rb_cPGresult = rb_define_class_under( rb_mPG, "Result", rb_cData );
1619
+ rb_cPGresult = rb_define_class_under( rb_mPG, "Result", rb_cObject );
1620
+ rb_undef_alloc_func(rb_cPGresult);
1591
1621
  rb_include_module(rb_cPGresult, rb_mEnumerable);
1592
1622
  rb_include_module(rb_cPGresult, rb_mPGconstants);
1593
1623
 
@@ -854,7 +854,7 @@ pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
854
854
 
855
855
  ip_int_native = read_nbo32(dst);
856
856
 
857
- /* Work around broken IPAddr behavior of convering portion
857
+ /* Work around broken IPAddr behavior of converting portion
858
858
  of address after netmask to 0 */
859
859
  switch (mask) {
860
860
  case 0:
@@ -191,7 +191,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
191
191
  if (neg)
192
192
  *out++ = '-';
193
193
 
194
- len = out - start;
194
+ len = (int)(out - start);
195
195
 
196
196
  /* Reverse string. */
197
197
  out--;
@@ -252,7 +252,7 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
252
252
  }
253
253
 
254
254
  /*
255
- * The following computaion is roughly a conversion kind of
255
+ * The following computation is roughly a conversion kind of
256
256
  * sprintf( out, "%.16E", dvalue);
257
257
  */
258
258
 
@@ -403,11 +403,11 @@ pg_text_enc_bytea(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
403
403
  *optr++ = hextab[c >> 4];
404
404
  *optr++ = hextab[c & 0xf];
405
405
  }
406
- return optr - out;
406
+ return (int)(optr - out);
407
407
  }else{
408
408
  *intermediate = rb_obj_as_string(value);
409
409
  /* The output starts with "\x" and each character is converted to hex. */
410
- return 2 + RSTRING_LEN(*intermediate) * 2;
410
+ return 2 + RSTRING_LENINT(*intermediate) * 2;
411
411
  }
412
412
  }
413
413
 
@@ -610,8 +610,8 @@ quote_identifier( VALUE value, VALUE out_string, char *current_out ){
610
610
  static char *
611
611
  pg_text_enc_array_identifier(VALUE value, VALUE string, char *out, int enc_idx)
612
612
  {
613
- int i;
614
- int nr_elems;
613
+ long i;
614
+ long nr_elems;
615
615
 
616
616
  Check_Type(value, T_ARRAY);
617
617
  nr_elems = RARRAY_LEN(value);
data/ext/pg_tuple.c CHANGED
@@ -52,57 +52,83 @@ typedef struct {
52
52
  VALUE values[0];
53
53
  } t_pg_tuple;
54
54
 
55
- static inline VALUE
56
- pg_tuple_get_field_names( t_pg_tuple *this )
55
+ static inline VALUE *
56
+ pg_tuple_get_field_names_ptr( t_pg_tuple *this )
57
57
  {
58
58
  if( this->num_fields != (int)RHASH_SIZE(this->field_map) ){
59
- return this->values[this->num_fields];
59
+ return &this->values[this->num_fields];
60
60
  } else {
61
- return Qfalse;
61
+ static VALUE f = Qfalse;
62
+ return &f;
63
+ }
64
+ }
65
+
66
+ static inline VALUE
67
+ pg_tuple_get_field_names( t_pg_tuple *this )
68
+ {
69
+ return *pg_tuple_get_field_names_ptr(this);
70
+ }
71
+
72
+ static void
73
+ pg_tuple_gc_mark( void *_this )
74
+ {
75
+ t_pg_tuple *this = (t_pg_tuple *)_this;
76
+ int i;
77
+
78
+ if( !this ) return;
79
+ rb_gc_mark_movable( this->result );
80
+ rb_gc_mark_movable( this->typemap );
81
+ rb_gc_mark_movable( this->field_map );
82
+
83
+ for( i = 0; i < this->num_fields; i++ ){
84
+ rb_gc_mark_movable( this->values[i] );
62
85
  }
86
+ rb_gc_mark_movable( pg_tuple_get_field_names(this) );
63
87
  }
64
88
 
65
89
  static void
66
- pg_tuple_gc_mark( t_pg_tuple *this )
90
+ pg_tuple_gc_compact( void *_this )
67
91
  {
92
+ t_pg_tuple *this = (t_pg_tuple *)_this;
68
93
  int i;
69
94
 
70
95
  if( !this ) return;
71
- rb_gc_mark( this->result );
72
- rb_gc_mark( this->typemap );
73
- rb_gc_mark( this->field_map );
96
+ pg_gc_location( this->result );
97
+ pg_gc_location( this->typemap );
98
+ pg_gc_location( this->field_map );
74
99
 
75
100
  for( i = 0; i < this->num_fields; i++ ){
76
- rb_gc_mark( this->values[i] );
101
+ pg_gc_location( this->values[i] );
77
102
  }
78
- rb_gc_mark( pg_tuple_get_field_names(this) );
103
+ pg_gc_location( *pg_tuple_get_field_names_ptr(this) );
79
104
  }
80
105
 
81
106
  static void
82
- pg_tuple_gc_free( t_pg_tuple *this )
107
+ pg_tuple_gc_free( void *_this )
83
108
  {
109
+ t_pg_tuple *this = (t_pg_tuple *)_this;
84
110
  if( !this ) return;
85
111
  xfree(this);
86
112
  }
87
113
 
88
114
  static size_t
89
- pg_tuple_memsize( t_pg_tuple *this )
115
+ pg_tuple_memsize( const void *_this )
90
116
  {
117
+ const t_pg_tuple *this = (const t_pg_tuple *)_this;
91
118
  if( this==NULL ) return 0;
92
119
  return sizeof(*this) + sizeof(*this->values) * this->num_fields;
93
120
  }
94
121
 
95
122
  static const rb_data_type_t pg_tuple_type = {
96
- "pg",
123
+ "PG::Tuple",
97
124
  {
98
- (void (*)(void*))pg_tuple_gc_mark,
99
- (void (*)(void*))pg_tuple_gc_free,
100
- (size_t (*)(const void *))pg_tuple_memsize,
125
+ pg_tuple_gc_mark,
126
+ pg_tuple_gc_free,
127
+ pg_tuple_memsize,
128
+ pg_compact_callback(pg_tuple_gc_compact),
101
129
  },
102
130
  0, 0,
103
- #ifdef RUBY_TYPED_FREE_IMMEDIATELY
104
131
  RUBY_TYPED_FREE_IMMEDIATELY,
105
- #endif
106
132
  };
107
133
 
108
134
  /*
@@ -172,7 +198,7 @@ pg_tuple_materialize_field(t_pg_tuple *this, int col)
172
198
  VALUE value = this->values[col];
173
199
 
174
200
  if( value == Qundef ){
175
- t_typemap *p_typemap = DATA_PTR( this->typemap );
201
+ t_typemap *p_typemap = RTYPEDDATA_DATA( this->typemap );
176
202
 
177
203
  pgresult_get(this->result); /* make sure we have a valid PGresult object */
178
204
  value = p_typemap->funcs.typecast_result_value(p_typemap, this->result, this->row_num, col);
@@ -479,9 +505,9 @@ pg_tuple_load(VALUE self, VALUE a)
479
505
  rb_obj_freeze(field_names);
480
506
  values = RARRAY_AREF(a, 1);
481
507
  Check_Type(values, T_ARRAY);
482
- num_fields = RARRAY_LEN(values);
508
+ num_fields = RARRAY_LENINT(values);
483
509
 
484
- if (RARRAY_LEN(field_names) != num_fields)
510
+ if (RARRAY_LENINT(field_names) != num_fields)
485
511
  rb_raise(rb_eTypeError, "different number of fields and values");
486
512
 
487
513
  field_map = rb_hash_new();