pg 1.2.3 → 1.3.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +80 -0
- data/.github/workflows/source-gem.yml +129 -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/Gemfile +14 -0
- data/History.rdoc +75 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +7 -6
- data/Rakefile +27 -138
- data/Rakefile.cross +5 -5
- data/certs/ged.pem +24 -0
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.txt +3 -1
- data/ext/extconf.rb +90 -19
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +35 -1
- data/ext/pg.h +18 -1
- data/ext/pg_coder.c +82 -28
- data/ext/pg_connection.c +538 -279
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +38 -10
- data/ext/pg_result.c +61 -31
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -6
- data/ext/pg_tuple.c +47 -21
- data/ext/pg_type_map.c +41 -8
- data/ext/pg_type_map_all_strings.c +14 -1
- data/ext/pg_type_map_by_class.c +49 -24
- data/ext/pg_type_map_by_column.c +64 -28
- data/ext/pg_type_map_by_mri_type.c +47 -18
- data/ext/pg_type_map_by_oid.c +52 -23
- data/ext/pg_type_map_in_ruby.c +50 -19
- data/ext/pg_util.c +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 +296 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +369 -56
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +38 -25
- 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/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +106 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +79 -226
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- 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 -1123
- 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(
|
24
|
+
pg_copycoder_mark( void *_this )
|
25
25
|
{
|
26
|
-
|
27
|
-
|
28
|
-
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
|
429
|
+
long input_len;
|
401
430
|
|
402
431
|
/* Remember start of field on input side */
|
403
432
|
start_ptr = cur_ptr;
|
data/ext/pg_record_coder.c
CHANGED
@@ -16,17 +16,45 @@ typedef struct {
|
|
16
16
|
|
17
17
|
|
18
18
|
static void
|
19
|
-
pg_recordcoder_mark(
|
19
|
+
pg_recordcoder_mark( void *_this )
|
20
20
|
{
|
21
|
-
|
22
|
-
|
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 =
|
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 =
|
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 =
|
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 =
|
107
|
+
t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
|
80
108
|
|
81
109
|
return this->typemap;
|
82
110
|
}
|
@@ -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 =
|
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
|
-
|
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 =
|
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(
|
110
|
+
pgresult_gc_mark( void *_this )
|
111
111
|
{
|
112
|
+
t_pg_result *this = (t_pg_result *)_this;
|
112
113
|
int i;
|
113
114
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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
|
-
"
|
178
|
+
"PG::Result",
|
159
179
|
{
|
160
|
-
|
161
|
-
|
162
|
-
|
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 =
|
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 =
|
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 =
|
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
|
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::
|
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
|
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
|
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
|
-
|
1329
|
-
|
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 =
|
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",
|
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
|
|
data/ext/pg_text_decoder.c
CHANGED
@@ -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
|
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:
|
data/ext/pg_text_encoder.c
CHANGED
@@ -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
|
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 +
|
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
|
-
|
614
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
101
|
+
pg_gc_location( this->values[i] );
|
77
102
|
}
|
78
|
-
|
103
|
+
pg_gc_location( *pg_tuple_get_field_names_ptr(this) );
|
79
104
|
}
|
80
105
|
|
81
106
|
static void
|
82
|
-
pg_tuple_gc_free(
|
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(
|
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
|
-
"
|
123
|
+
"PG::Tuple",
|
97
124
|
{
|
98
|
-
|
99
|
-
|
100
|
-
|
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 =
|
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 =
|
508
|
+
num_fields = RARRAY_LENINT(values);
|
483
509
|
|
484
|
-
if (
|
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();
|