pg 0.18.2 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +86 -0
- data/.github/workflows/source-gem.yml +131 -0
- data/.gitignore +13 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/BSDL +2 -2
- data/Gemfile +14 -0
- data/History.rdoc +480 -4
- data/Manifest.txt +8 -21
- data/README-Windows.rdoc +17 -28
- data/README.ja.rdoc +1 -2
- data/README.rdoc +92 -20
- data/Rakefile +33 -133
- data/Rakefile.cross +89 -67
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/ext/errorcodes.def +113 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +36 -2
- data/ext/extconf.rb +120 -54
- data/ext/gvl_wrappers.c +8 -0
- data/ext/gvl_wrappers.h +44 -33
- data/ext/pg.c +216 -172
- data/ext/pg.h +93 -98
- data/ext/pg_binary_decoder.c +85 -16
- data/ext/pg_binary_encoder.c +25 -22
- data/ext/pg_coder.c +176 -40
- data/ext/pg_connection.c +1735 -1138
- data/ext/pg_copy_coder.c +95 -28
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +521 -0
- data/ext/pg_result.c +642 -221
- data/ext/pg_text_decoder.c +609 -41
- data/ext/pg_text_encoder.c +254 -100
- data/ext/pg_tuple.c +569 -0
- data/ext/pg_type_map.c +62 -22
- data/ext/pg_type_map_all_strings.c +20 -6
- data/ext/pg_type_map_by_class.c +55 -25
- data/ext/pg_type_map_by_column.c +81 -42
- data/ext/pg_type_map_by_mri_type.c +49 -20
- data/ext/pg_type_map_by_oid.c +56 -26
- data/ext/pg_type_map_in_ruby.c +52 -21
- data/ext/{util.c → pg_util.c} +12 -12
- data/ext/{util.h → pg_util.h} +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +47 -0
- data/lib/pg/basic_type_map_for_queries.rb +193 -0
- data/lib/pg/basic_type_map_for_results.rb +81 -0
- data/lib/pg/basic_type_registry.rb +301 -0
- data/lib/pg/binary_decoder.rb +23 -0
- data/lib/pg/coder.rb +24 -3
- data/lib/pg/connection.rb +711 -64
- data/lib/pg/constants.rb +2 -1
- data/lib/pg/exceptions.rb +9 -2
- data/lib/pg/result.rb +24 -7
- data/lib/pg/text_decoder.rb +27 -23
- data/lib/pg/text_encoder.rb +40 -8
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +3 -2
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +61 -36
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +32 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +1 -1
- data/sample/async_api.rb +4 -8
- data/sample/async_copyto.rb +1 -1
- data/sample/async_mixed.rb +1 -1
- data/sample/check_conn.rb +1 -1
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +1 -1
- data/sample/copyto.rb +1 -1
- data/sample/cursor.rb +1 -1
- data/sample/disk_usage_report.rb +6 -15
- data/sample/issue-119.rb +2 -2
- data/sample/losample.rb +1 -1
- data/sample/minimal-testcase.rb +2 -2
- data/sample/notify_wait.rb +1 -1
- data/sample/pg_statistics.rb +6 -15
- data/sample/replication_monitor.rb +9 -18
- data/sample/test_binary_values.rb +1 -1
- data/sample/wal_shipper.rb +2 -2
- data/sample/warehouse_partitions.rb +8 -17
- data.tar.gz.sig +0 -0
- metadata +74 -216
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -5545
- data/lib/pg/basic_type_mapping.rb +0 -399
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -355
- data/spec/pg/basic_type_mapping_spec.rb +0 -251
- data/spec/pg/connection_spec.rb +0 -1535
- data/spec/pg/result_spec.rb +0 -449
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -222
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -688
- data/spec/pg_spec.rb +0 -50
data/ext/pg_copy_coder.c
CHANGED
|
@@ -21,17 +21,47 @@ typedef struct {
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
static void
|
|
24
|
-
pg_copycoder_mark(
|
|
24
|
+
pg_copycoder_mark( void *_this )
|
|
25
25
|
{
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
t_pg_copycoder *this = (t_pg_copycoder *)_this;
|
|
27
|
+
rb_gc_mark_movable(this->typemap);
|
|
28
|
+
rb_gc_mark_movable(this->null_string);
|
|
28
29
|
}
|
|
29
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
|
+
|
|
30
60
|
static VALUE
|
|
31
61
|
pg_copycoder_encoder_allocate( VALUE klass )
|
|
32
62
|
{
|
|
33
63
|
t_pg_copycoder *this;
|
|
34
|
-
VALUE self =
|
|
64
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
|
|
35
65
|
pg_coder_init_encoder( self );
|
|
36
66
|
this->typemap = pg_typemap_all_strings;
|
|
37
67
|
this->delimiter = '\t';
|
|
@@ -43,7 +73,7 @@ static VALUE
|
|
|
43
73
|
pg_copycoder_decoder_allocate( VALUE klass )
|
|
44
74
|
{
|
|
45
75
|
t_pg_copycoder *this;
|
|
46
|
-
VALUE self =
|
|
76
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_copycoder, &pg_copycoder_type, this );
|
|
47
77
|
pg_coder_init_decoder( self );
|
|
48
78
|
this->typemap = pg_typemap_all_strings;
|
|
49
79
|
this->delimiter = '\t';
|
|
@@ -62,7 +92,7 @@ pg_copycoder_decoder_allocate( VALUE klass )
|
|
|
62
92
|
static VALUE
|
|
63
93
|
pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
|
|
64
94
|
{
|
|
65
|
-
t_pg_copycoder *this =
|
|
95
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA(self);
|
|
66
96
|
StringValue(delimiter);
|
|
67
97
|
if(RSTRING_LEN(delimiter) != 1)
|
|
68
98
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
|
@@ -79,7 +109,7 @@ pg_copycoder_delimiter_set(VALUE self, VALUE delimiter)
|
|
|
79
109
|
static VALUE
|
|
80
110
|
pg_copycoder_delimiter_get(VALUE self)
|
|
81
111
|
{
|
|
82
|
-
t_pg_copycoder *this =
|
|
112
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA(self);
|
|
83
113
|
return rb_str_new(&this->delimiter, 1);
|
|
84
114
|
}
|
|
85
115
|
|
|
@@ -92,7 +122,7 @@ pg_copycoder_delimiter_get(VALUE self)
|
|
|
92
122
|
static VALUE
|
|
93
123
|
pg_copycoder_null_string_set(VALUE self, VALUE null_string)
|
|
94
124
|
{
|
|
95
|
-
t_pg_copycoder *this =
|
|
125
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA(self);
|
|
96
126
|
StringValue(null_string);
|
|
97
127
|
this->null_string = null_string;
|
|
98
128
|
return null_string;
|
|
@@ -104,7 +134,7 @@ pg_copycoder_null_string_set(VALUE self, VALUE null_string)
|
|
|
104
134
|
static VALUE
|
|
105
135
|
pg_copycoder_null_string_get(VALUE self)
|
|
106
136
|
{
|
|
107
|
-
t_pg_copycoder *this =
|
|
137
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA(self);
|
|
108
138
|
return this->null_string;
|
|
109
139
|
}
|
|
110
140
|
|
|
@@ -112,16 +142,17 @@ pg_copycoder_null_string_get(VALUE self)
|
|
|
112
142
|
* call-seq:
|
|
113
143
|
* coder.type_map = map
|
|
114
144
|
*
|
|
145
|
+
* Defines how single columns are encoded or decoded.
|
|
115
146
|
* +map+ must be a kind of PG::TypeMap .
|
|
116
147
|
*
|
|
117
148
|
* Defaults to a PG::TypeMapAllStrings , so that PG::TextEncoder::String respectively
|
|
118
|
-
* PG::TextDecoder::String is used for encoding/decoding of
|
|
149
|
+
* PG::TextDecoder::String is used for encoding/decoding of each column.
|
|
119
150
|
*
|
|
120
151
|
*/
|
|
121
152
|
static VALUE
|
|
122
153
|
pg_copycoder_type_map_set(VALUE self, VALUE type_map)
|
|
123
154
|
{
|
|
124
|
-
t_pg_copycoder *this =
|
|
155
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA( self );
|
|
125
156
|
|
|
126
157
|
if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
|
|
127
158
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
|
|
@@ -136,11 +167,12 @@ pg_copycoder_type_map_set(VALUE self, VALUE type_map)
|
|
|
136
167
|
* call-seq:
|
|
137
168
|
* coder.type_map -> PG::TypeMap
|
|
138
169
|
*
|
|
170
|
+
* The PG::TypeMap that will be used for encoding and decoding of columns.
|
|
139
171
|
*/
|
|
140
172
|
static VALUE
|
|
141
173
|
pg_copycoder_type_map_get(VALUE self)
|
|
142
174
|
{
|
|
143
|
-
t_pg_copycoder *this =
|
|
175
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA( self );
|
|
144
176
|
|
|
145
177
|
return this->typemap;
|
|
146
178
|
}
|
|
@@ -167,9 +199,15 @@ pg_copycoder_type_map_get(VALUE self)
|
|
|
167
199
|
* conn.put_copy_data ["string2", 42, true]
|
|
168
200
|
* end
|
|
169
201
|
* This creates +my_table+ and inserts two rows.
|
|
202
|
+
*
|
|
203
|
+
* It is possible to manually assign a type encoder for each column per PG::TypeMapByColumn,
|
|
204
|
+
* or to make use of PG::BasicTypeMapBasedOnResult to assign them based on the table OIDs.
|
|
205
|
+
*
|
|
206
|
+
* See also PG::TextDecoder::CopyRow for the decoding direction with
|
|
207
|
+
* PG::Connection#get_copy_data .
|
|
170
208
|
*/
|
|
171
209
|
static int
|
|
172
|
-
pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
210
|
+
pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
173
211
|
{
|
|
174
212
|
t_pg_copycoder *this = (t_pg_copycoder *)conv;
|
|
175
213
|
t_pg_coder_enc_func enc_func;
|
|
@@ -179,11 +217,12 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
179
217
|
char *current_out;
|
|
180
218
|
char *end_capa_ptr;
|
|
181
219
|
|
|
182
|
-
p_typemap =
|
|
220
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
|
183
221
|
p_typemap->funcs.fit_to_query( this->typemap, value );
|
|
184
222
|
|
|
185
223
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
|
186
224
|
PG_RB_STR_NEW( *intermediate, current_out, end_capa_ptr );
|
|
225
|
+
PG_ENCODING_SET_NOCHECK(*intermediate, enc_idx);
|
|
187
226
|
|
|
188
227
|
for( i=0; i<RARRAY_LEN(value); i++){
|
|
189
228
|
char *ptr1;
|
|
@@ -211,11 +250,11 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
211
250
|
enc_func = pg_coder_enc_func(p_elem_coder);
|
|
212
251
|
|
|
213
252
|
/* 1st pass for retiving the required memory space */
|
|
214
|
-
strlen = enc_func(p_elem_coder, entry, NULL, &subint);
|
|
253
|
+
strlen = enc_func(p_elem_coder, entry, NULL, &subint, enc_idx);
|
|
215
254
|
|
|
216
255
|
if( strlen == -1 ){
|
|
217
256
|
/* we can directly use String value in subint */
|
|
218
|
-
strlen =
|
|
257
|
+
strlen = RSTRING_LENINT(subint);
|
|
219
258
|
|
|
220
259
|
/* size of string assuming the worst case, that every character must be escaped. */
|
|
221
260
|
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
|
@@ -234,7 +273,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
|
234
273
|
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
|
235
274
|
|
|
236
275
|
/* Place the unescaped string at current output position. */
|
|
237
|
-
strlen = enc_func(p_elem_coder, entry, current_out, &subint);
|
|
276
|
+
strlen = enc_func(p_elem_coder, entry, current_out, &subint, enc_idx);
|
|
238
277
|
|
|
239
278
|
ptr1 = current_out;
|
|
240
279
|
ptr2 = current_out + strlen;
|
|
@@ -301,15 +340,38 @@ GetDecimalFromHex(char hex)
|
|
|
301
340
|
* strings by PG::TextDecoder::String.
|
|
302
341
|
*
|
|
303
342
|
* Example with default type map ( TypeMapAllStrings ):
|
|
343
|
+
* conn.exec("CREATE TABLE my_table AS VALUES('astring', 7, FALSE), ('string2', 42, TRUE) ")
|
|
344
|
+
*
|
|
304
345
|
* deco = PG::TextDecoder::CopyRow.new
|
|
305
346
|
* conn.copy_data "COPY my_table TO STDOUT", deco do
|
|
306
347
|
* while row=conn.get_copy_data
|
|
307
348
|
* p row
|
|
308
349
|
* end
|
|
309
350
|
* end
|
|
310
|
-
* This prints all rows of +my_table+
|
|
351
|
+
* This prints all rows of +my_table+ :
|
|
311
352
|
* ["astring", "7", "f"]
|
|
312
353
|
* ["string2", "42", "t"]
|
|
354
|
+
*
|
|
355
|
+
* Example with column based type map:
|
|
356
|
+
* tm = PG::TypeMapByColumn.new( [
|
|
357
|
+
* PG::TextDecoder::String.new,
|
|
358
|
+
* PG::TextDecoder::Integer.new,
|
|
359
|
+
* PG::TextDecoder::Boolean.new] )
|
|
360
|
+
* deco = PG::TextDecoder::CopyRow.new( type_map: tm )
|
|
361
|
+
* conn.copy_data "COPY my_table TO STDOUT", deco do
|
|
362
|
+
* while row=conn.get_copy_data
|
|
363
|
+
* p row
|
|
364
|
+
* end
|
|
365
|
+
* end
|
|
366
|
+
* This prints the rows with type casted columns:
|
|
367
|
+
* ["astring", 7, false]
|
|
368
|
+
* ["string2", 42, true]
|
|
369
|
+
*
|
|
370
|
+
* Instead of manually assigning a type decoder for each column, PG::BasicTypeMapForResults
|
|
371
|
+
* can be used to assign them based on the table OIDs.
|
|
372
|
+
*
|
|
373
|
+
* See also PG::TextEncoder::CopyRow for the encoding direction with
|
|
374
|
+
* PG::Connection#put_copy_data .
|
|
313
375
|
*/
|
|
314
376
|
/*
|
|
315
377
|
* Parse the current line into separate attributes (fields),
|
|
@@ -324,7 +386,7 @@ GetDecimalFromHex(char hex)
|
|
|
324
386
|
* src/backend/commands/copy.c
|
|
325
387
|
*/
|
|
326
388
|
static VALUE
|
|
327
|
-
pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, int _field, int enc_idx)
|
|
389
|
+
pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tuple, int _field, int enc_idx)
|
|
328
390
|
{
|
|
329
391
|
t_pg_copycoder *this = (t_pg_copycoder *)conv;
|
|
330
392
|
|
|
@@ -338,12 +400,12 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
|
|
|
338
400
|
int fieldno;
|
|
339
401
|
int expected_fields;
|
|
340
402
|
char *output_ptr;
|
|
341
|
-
char *cur_ptr;
|
|
342
|
-
char *line_end_ptr;
|
|
403
|
+
const char *cur_ptr;
|
|
404
|
+
const char *line_end_ptr;
|
|
343
405
|
char *end_capa_ptr;
|
|
344
406
|
t_typemap *p_typemap;
|
|
345
407
|
|
|
346
|
-
p_typemap =
|
|
408
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
|
347
409
|
expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
|
|
348
410
|
|
|
349
411
|
/* The received input string will probably have this->nfields fields. */
|
|
@@ -351,7 +413,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
|
|
|
351
413
|
|
|
352
414
|
/* Allocate a new string with embedded capacity and realloc later with
|
|
353
415
|
* exponential growing size when needed. */
|
|
354
|
-
|
|
416
|
+
PG_RB_STR_NEW( field_str, output_ptr, end_capa_ptr );
|
|
355
417
|
|
|
356
418
|
/* set pointer variables for loop */
|
|
357
419
|
cur_ptr = input_line;
|
|
@@ -362,9 +424,9 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
|
|
|
362
424
|
for (;;)
|
|
363
425
|
{
|
|
364
426
|
int found_delim = 0;
|
|
365
|
-
char *start_ptr;
|
|
366
|
-
char *end_ptr;
|
|
367
|
-
|
|
427
|
+
const char *start_ptr;
|
|
428
|
+
const char *end_ptr;
|
|
429
|
+
long input_len;
|
|
368
430
|
|
|
369
431
|
/* Remember start of field on input side */
|
|
370
432
|
start_ptr = cur_ptr;
|
|
@@ -513,7 +575,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
|
|
|
513
575
|
if( field_value == field_str ){
|
|
514
576
|
/* Our output string will be send to the user, so we can not reuse
|
|
515
577
|
* it for the next field. */
|
|
516
|
-
|
|
578
|
+
PG_RB_STR_NEW( field_str, output_ptr, end_capa_ptr );
|
|
517
579
|
}
|
|
518
580
|
}
|
|
519
581
|
/* Reset the pointer to the start of the output/buffer string. */
|
|
@@ -530,7 +592,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, char *input_line, int len, int _tuple, in
|
|
|
530
592
|
|
|
531
593
|
|
|
532
594
|
void
|
|
533
|
-
init_pg_copycoder()
|
|
595
|
+
init_pg_copycoder(void)
|
|
534
596
|
{
|
|
535
597
|
/* Document-class: PG::CopyCoder < PG::Coder
|
|
536
598
|
*
|
|
@@ -555,7 +617,12 @@ init_pg_copycoder()
|
|
|
555
617
|
/* rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" ); */
|
|
556
618
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "CopyRow", rb_cPG_CopyEncoder ); */
|
|
557
619
|
pg_define_coder( "CopyRow", pg_text_enc_copy_row, rb_cPG_CopyEncoder, rb_mPG_TextEncoder );
|
|
620
|
+
rb_include_module( rb_cPG_CopyEncoder, rb_mPG_BinaryFormatting );
|
|
621
|
+
|
|
558
622
|
/* rb_mPG_TextDecoder = rb_define_module_under( rb_mPG, "TextDecoder" ); */
|
|
559
623
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "CopyRow", rb_cPG_CopyDecoder ); */
|
|
560
624
|
pg_define_coder( "CopyRow", pg_text_dec_copy_row, rb_cPG_CopyDecoder, rb_mPG_TextDecoder );
|
|
625
|
+
/* Although CopyRow is a text decoder, data can contain zero bytes and are not zero terminated.
|
|
626
|
+
* They are handled like binaries. So format is set to 1 (binary). */
|
|
627
|
+
rb_include_module( rb_cPG_CopyDecoder, rb_mPG_BinaryFormatting );
|
|
561
628
|
}
|