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.
- 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 +98 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +9 -8
- data/Rakefile +31 -140
- data/Rakefile.cross +54 -56
- 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 -0
- data/ext/pg_coder.c +90 -24
- data/ext/pg_connection.c +538 -279
- data/ext/pg_copy_coder.c +45 -15
- data/ext/pg_record_coder.c +38 -9
- data/ext/pg_result.c +70 -34
- 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 +50 -21
- 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/2.5/pg_ext.so +0 -0
- data/lib/2.6/pg_ext.so +0 -0
- data/lib/2.7/pg_ext.so +0 -0
- data/lib/3.0/pg_ext.so +0 -0
- 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 -24
- data/lib/x86-mingw32/libpq.dll +0 -0
- 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 +83 -232
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/2.4/pg_ext.so +0 -0
- data/lib/libpq.dll +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 -382
- data/spec/pg/basic_type_mapping_spec.rb +0 -645
- data/spec/pg/connection_spec.rb +0 -1911
- 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,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
|
|
@@ -122,7 +152,7 @@ pg_copycoder_null_string_get(VALUE self)
|
|
122
152
|
static VALUE
|
123
153
|
pg_copycoder_type_map_set(VALUE self, VALUE type_map)
|
124
154
|
{
|
125
|
-
t_pg_copycoder *this =
|
155
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA( self );
|
126
156
|
|
127
157
|
if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
|
128
158
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
|
@@ -142,7 +172,7 @@ pg_copycoder_type_map_set(VALUE self, VALUE type_map)
|
|
142
172
|
static VALUE
|
143
173
|
pg_copycoder_type_map_get(VALUE self)
|
144
174
|
{
|
145
|
-
t_pg_copycoder *this =
|
175
|
+
t_pg_copycoder *this = RTYPEDDATA_DATA( self );
|
146
176
|
|
147
177
|
return this->typemap;
|
148
178
|
}
|
@@ -187,7 +217,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
187
217
|
char *current_out;
|
188
218
|
char *end_capa_ptr;
|
189
219
|
|
190
|
-
p_typemap =
|
220
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
191
221
|
p_typemap->funcs.fit_to_query( this->typemap, value );
|
192
222
|
|
193
223
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
@@ -224,7 +254,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
224
254
|
|
225
255
|
if( strlen == -1 ){
|
226
256
|
/* we can directly use String value in subint */
|
227
|
-
strlen =
|
257
|
+
strlen = RSTRING_LENINT(subint);
|
228
258
|
|
229
259
|
/* size of string assuming the worst case, that every character must be escaped. */
|
230
260
|
PG_RB_STR_ENSURE_CAPA( *intermediate, strlen * 2, current_out, end_capa_ptr );
|
@@ -375,7 +405,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
375
405
|
char *end_capa_ptr;
|
376
406
|
t_typemap *p_typemap;
|
377
407
|
|
378
|
-
p_typemap =
|
408
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
379
409
|
expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
|
380
410
|
|
381
411
|
/* The received input string will probably have this->nfields fields. */
|
@@ -396,7 +426,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
|
|
396
426
|
int found_delim = 0;
|
397
427
|
const char *start_ptr;
|
398
428
|
const char *end_ptr;
|
399
|
-
|
429
|
+
long input_len;
|
400
430
|
|
401
431
|
/* Remember start of field on input side */
|
402
432
|
start_ptr = cur_ptr;
|
data/ext/pg_record_coder.c
CHANGED
@@ -16,16 +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
|
-
|
21
|
+
t_pg_recordcoder *this = (t_pg_recordcoder *)_this;
|
22
|
+
rb_gc_mark_movable(this->typemap);
|
22
23
|
}
|
23
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
|
+
|
24
53
|
static VALUE
|
25
54
|
pg_recordcoder_encoder_allocate( VALUE klass )
|
26
55
|
{
|
27
56
|
t_pg_recordcoder *this;
|
28
|
-
VALUE self =
|
57
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
|
29
58
|
pg_coder_init_encoder( self );
|
30
59
|
this->typemap = pg_typemap_all_strings;
|
31
60
|
return self;
|
@@ -35,7 +64,7 @@ static VALUE
|
|
35
64
|
pg_recordcoder_decoder_allocate( VALUE klass )
|
36
65
|
{
|
37
66
|
t_pg_recordcoder *this;
|
38
|
-
VALUE self =
|
67
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_recordcoder, &pg_recordcoder_type, this );
|
39
68
|
pg_coder_init_decoder( self );
|
40
69
|
this->typemap = pg_typemap_all_strings;
|
41
70
|
return self;
|
@@ -55,7 +84,7 @@ pg_recordcoder_decoder_allocate( VALUE klass )
|
|
55
84
|
static VALUE
|
56
85
|
pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
|
57
86
|
{
|
58
|
-
t_pg_recordcoder *this =
|
87
|
+
t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
|
59
88
|
|
60
89
|
if ( !rb_obj_is_kind_of(type_map, rb_cTypeMap) ){
|
61
90
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::TypeMap)",
|
@@ -75,7 +104,7 @@ pg_recordcoder_type_map_set(VALUE self, VALUE type_map)
|
|
75
104
|
static VALUE
|
76
105
|
pg_recordcoder_type_map_get(VALUE self)
|
77
106
|
{
|
78
|
-
t_pg_recordcoder *this =
|
107
|
+
t_pg_recordcoder *this = RTYPEDDATA_DATA( self );
|
79
108
|
|
80
109
|
return this->typemap;
|
81
110
|
}
|
@@ -155,7 +184,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
155
184
|
char *current_out;
|
156
185
|
char *end_capa_ptr;
|
157
186
|
|
158
|
-
p_typemap =
|
187
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
159
188
|
p_typemap->funcs.fit_to_query( this->typemap, value );
|
160
189
|
|
161
190
|
/* Allocate a new string with embedded capacity and realloc exponential when needed. */
|
@@ -167,7 +196,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
167
196
|
for( i=0; i<RARRAY_LEN(value); i++){
|
168
197
|
char *ptr1;
|
169
198
|
char *ptr2;
|
170
|
-
|
199
|
+
long strlen;
|
171
200
|
int backslashs;
|
172
201
|
VALUE subint;
|
173
202
|
VALUE entry;
|
@@ -357,7 +386,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
|
|
357
386
|
char *end_capa_ptr;
|
358
387
|
t_typemap *p_typemap;
|
359
388
|
|
360
|
-
p_typemap =
|
389
|
+
p_typemap = RTYPEDDATA_DATA( this->typemap );
|
361
390
|
expected_fields = p_typemap->funcs.fit_to_copy_get( this->typemap );
|
362
391
|
|
363
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,18 +175,22 @@ 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
|
|
189
|
+
/* Needed by sequel_pg gem, do not delete */
|
190
|
+
int pg_get_result_enc_idx(VALUE self)
|
191
|
+
{
|
192
|
+
return pgresult_get_this(self)->enc_idx;
|
193
|
+
}
|
170
194
|
|
171
195
|
/*
|
172
196
|
* Global functions
|
@@ -186,7 +210,7 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
|
|
186
210
|
this->pgresult = result;
|
187
211
|
this->connection = rb_pgconn;
|
188
212
|
this->typemap = pg_typemap_all_strings;
|
189
|
-
this->p_typemap =
|
213
|
+
this->p_typemap = RTYPEDDATA_DATA( this->typemap );
|
190
214
|
this->nfields = -1;
|
191
215
|
this->tuple_hash = Qnil;
|
192
216
|
this->field_map = Qnil;
|
@@ -197,11 +221,11 @@ pg_new_result2(PGresult *result, VALUE rb_pgconn)
|
|
197
221
|
t_pg_connection *p_conn = pg_get_connection(rb_pgconn);
|
198
222
|
VALUE typemap = p_conn->type_map_for_results;
|
199
223
|
/* Type check is done when assigned to PG::Connection. */
|
200
|
-
t_typemap *p_typemap =
|
224
|
+
t_typemap *p_typemap = RTYPEDDATA_DATA(typemap);
|
201
225
|
|
202
226
|
this->enc_idx = p_conn->enc_idx;
|
203
227
|
this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
|
204
|
-
this->p_typemap =
|
228
|
+
this->p_typemap = RTYPEDDATA_DATA( this->typemap );
|
205
229
|
this->flags = p_conn->flags;
|
206
230
|
} else {
|
207
231
|
this->enc_idx = rb_locale_encindex();
|
@@ -265,7 +289,11 @@ pg_new_result_autoclear(PGresult *result, VALUE rb_pgconn)
|
|
265
289
|
* call-seq:
|
266
290
|
* res.check -> nil
|
267
291
|
*
|
268
|
-
* 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+
|
269
297
|
*/
|
270
298
|
VALUE
|
271
299
|
pg_result_check( VALUE self )
|
@@ -290,10 +318,16 @@ pg_result_check( VALUE self )
|
|
290
318
|
case PGRES_SINGLE_TUPLE:
|
291
319
|
case PGRES_EMPTY_QUERY:
|
292
320
|
case PGRES_COMMAND_OK:
|
321
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
322
|
+
case PGRES_PIPELINE_SYNC:
|
323
|
+
#endif
|
293
324
|
return self;
|
294
325
|
case PGRES_BAD_RESPONSE:
|
295
326
|
case PGRES_FATAL_ERROR:
|
296
327
|
case PGRES_NONFATAL_ERROR:
|
328
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
329
|
+
case PGRES_PIPELINE_ABORTED:
|
330
|
+
#endif
|
297
331
|
error = rb_str_new2( PQresultErrorMessage(this->pgresult) );
|
298
332
|
break;
|
299
333
|
default:
|
@@ -333,8 +367,7 @@ pg_result_check( VALUE self )
|
|
333
367
|
* Special care must be taken when PG::Tuple objects are used.
|
334
368
|
* In this case #clear must not be called unless all PG::Tuple objects of this result are fully materialized.
|
335
369
|
*
|
336
|
-
* If PG::Result#autoclear? is true then the result is marked as cleared
|
337
|
-
* and the underlying C struct will be cleared automatically by libpq.
|
370
|
+
* If PG::Result#autoclear? is +true+ then the result is only marked as cleared but clearing the underlying C struct will happen when the callback returns.
|
338
371
|
*
|
339
372
|
*/
|
340
373
|
VALUE
|
@@ -349,7 +382,7 @@ pg_result_clear(VALUE self)
|
|
349
382
|
* call-seq:
|
350
383
|
* res.cleared? -> boolean
|
351
384
|
*
|
352
|
-
* Returns +true+ if the backend result memory has been
|
385
|
+
* Returns +true+ if the backend result memory has been freed.
|
353
386
|
*/
|
354
387
|
VALUE
|
355
388
|
pgresult_cleared_p( VALUE self )
|
@@ -362,8 +395,10 @@ pgresult_cleared_p( VALUE self )
|
|
362
395
|
* call-seq:
|
363
396
|
* res.autoclear? -> boolean
|
364
397
|
*
|
365
|
-
* Returns +true+ if the underlying C struct will be cleared
|
366
|
-
*
|
398
|
+
* Returns +true+ if the underlying C struct will be cleared at the end of a callback.
|
399
|
+
* This applies only to Result objects received by the block to PG::Connection#set_notice_receiver .
|
400
|
+
*
|
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 .
|
367
402
|
*
|
368
403
|
*/
|
369
404
|
VALUE
|
@@ -489,6 +524,9 @@ static void pgresult_init_fnames(VALUE self)
|
|
489
524
|
* * +PGRES_NONFATAL_ERROR+
|
490
525
|
* * +PGRES_FATAL_ERROR+
|
491
526
|
* * +PGRES_COPY_BOTH+
|
527
|
+
* * +PGRES_SINGLE_TUPLE+
|
528
|
+
* * +PGRES_PIPELINE_SYNC+
|
529
|
+
* * +PGRES_PIPELINE_ABORTED+
|
492
530
|
*/
|
493
531
|
static VALUE
|
494
532
|
pgresult_result_status(VALUE self)
|
@@ -500,7 +538,7 @@ pgresult_result_status(VALUE self)
|
|
500
538
|
* call-seq:
|
501
539
|
* res.res_status( status ) -> String
|
502
540
|
*
|
503
|
-
* Returns the string representation of
|
541
|
+
* Returns the string representation of +status+.
|
504
542
|
*
|
505
543
|
*/
|
506
544
|
static VALUE
|
@@ -997,7 +1035,7 @@ pgresult_cmd_tuples(VALUE self)
|
|
997
1035
|
{
|
998
1036
|
long n;
|
999
1037
|
n = strtol(PQcmdTuples(pgresult_get(self)),NULL, 10);
|
1000
|
-
return
|
1038
|
+
return LONG2NUM(n);
|
1001
1039
|
}
|
1002
1040
|
|
1003
1041
|
/*
|
@@ -1319,14 +1357,11 @@ pgresult_type_map_set(VALUE self, VALUE typemap)
|
|
1319
1357
|
t_pg_result *this = pgresult_get_this(self);
|
1320
1358
|
t_typemap *p_typemap;
|
1321
1359
|
|
1322
|
-
|
1323
|
-
|
1324
|
-
rb_obj_classname( typemap ) );
|
1325
|
-
}
|
1326
|
-
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);
|
1327
1362
|
|
1328
1363
|
this->typemap = p_typemap->funcs.fit_to_result( typemap, self );
|
1329
|
-
this->p_typemap =
|
1364
|
+
this->p_typemap = RTYPEDDATA_DATA( this->typemap );
|
1330
1365
|
|
1331
1366
|
return typemap;
|
1332
1367
|
}
|
@@ -1525,7 +1560,7 @@ pgresult_stream_each_tuple(VALUE self)
|
|
1525
1560
|
* It can be set to one of:
|
1526
1561
|
* * +:string+ to use String based field names
|
1527
1562
|
* * +:symbol+ to use Symbol based field names
|
1528
|
-
* * +: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.
|
1529
1564
|
*
|
1530
1565
|
* The default is retrieved from PG::Connection#field_name_type , which defaults to +:string+ .
|
1531
1566
|
*
|
@@ -1581,7 +1616,8 @@ init_pg_result()
|
|
1581
1616
|
sym_symbol = ID2SYM(rb_intern("symbol"));
|
1582
1617
|
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
1583
1618
|
|
1584
|
-
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);
|
1585
1621
|
rb_include_module(rb_cPGresult, rb_mEnumerable);
|
1586
1622
|
rb_include_module(rb_cPGresult, rb_mPGconstants);
|
1587
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();
|