pg 1.2.0-x86-mingw32 → 1.3.0.rc1-x86-mingw32
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 +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();
|