pg 1.4.6-x64-mingw32 → 1.5.0-x64-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 +1 -1
- data/.gitignore +3 -0
- data/History.md +55 -0
- data/README.ja.md +29 -19
- data/README.md +29 -15
- data/Rakefile.cross +1 -1
- data/ext/pg.c +10 -28
- data/ext/pg.h +10 -5
- data/ext/pg_binary_decoder.c +79 -0
- data/ext/pg_binary_encoder.c +224 -0
- data/ext/pg_coder.c +16 -7
- data/ext/pg_connection.c +50 -34
- data/ext/pg_copy_coder.c +306 -17
- data/ext/pg_record_coder.c +5 -4
- data/ext/pg_result.c +88 -17
- data/ext/pg_text_decoder.c +28 -10
- data/ext/pg_text_encoder.c +22 -9
- data/ext/pg_tuple.c +34 -31
- data/ext/pg_type_map.c +3 -2
- data/ext/pg_type_map_all_strings.c +2 -2
- data/ext/pg_type_map_by_class.c +5 -3
- data/ext/pg_type_map_by_column.c +9 -3
- data/ext/pg_type_map_by_oid.c +7 -4
- data/ext/pg_type_map_in_ruby.c +5 -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 +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +13 -8
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +30 -32
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +15 -13
- data/lib/pg/connection.rb +63 -12
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +44 -9
- data/lib/x64-mingw32/libpq.dll +0 -0
- data/pg.gemspec +1 -1
- data/translation/po/all.pot +170 -135
- data/translation/po/ja.po +365 -186
- data/translation/po4a.cfg +4 -1
- data.tar.gz.sig +0 -0
- metadata +28 -10
- metadata.gz.sig +0 -0
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
data/ext/pg_binary_encoder.c
CHANGED
@@ -11,6 +11,9 @@
|
|
11
11
|
#endif
|
12
12
|
|
13
13
|
VALUE rb_mPG_BinaryEncoder;
|
14
|
+
static ID s_id_year;
|
15
|
+
static ID s_id_month;
|
16
|
+
static ID s_id_day;
|
14
17
|
|
15
18
|
|
16
19
|
/*
|
@@ -93,6 +96,215 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
93
96
|
return 8;
|
94
97
|
}
|
95
98
|
|
99
|
+
/*
|
100
|
+
* Document-class: PG::BinaryEncoder::Float4 < PG::SimpleEncoder
|
101
|
+
*
|
102
|
+
* This is the binary encoder class for the PostgreSQL +float4+ type.
|
103
|
+
*
|
104
|
+
*/
|
105
|
+
static int
|
106
|
+
pg_bin_enc_float4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
107
|
+
{
|
108
|
+
union {
|
109
|
+
float f;
|
110
|
+
int32_t i;
|
111
|
+
} swap4;
|
112
|
+
|
113
|
+
if(out){
|
114
|
+
swap4.f = NUM2DBL(*intermediate);
|
115
|
+
write_nbo32(swap4.i, out);
|
116
|
+
}else{
|
117
|
+
*intermediate = value;
|
118
|
+
}
|
119
|
+
return 4;
|
120
|
+
}
|
121
|
+
|
122
|
+
/*
|
123
|
+
* Document-class: PG::BinaryEncoder::Float8 < PG::SimpleEncoder
|
124
|
+
*
|
125
|
+
* This is the binary encoder class for the PostgreSQL +float8+ type.
|
126
|
+
*
|
127
|
+
*/
|
128
|
+
static int
|
129
|
+
pg_bin_enc_float8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
130
|
+
{
|
131
|
+
union {
|
132
|
+
double f;
|
133
|
+
int64_t i;
|
134
|
+
} swap8;
|
135
|
+
|
136
|
+
if(out){
|
137
|
+
swap8.f = NUM2DBL(*intermediate);
|
138
|
+
write_nbo64(swap8.i, out);
|
139
|
+
}else{
|
140
|
+
*intermediate = value;
|
141
|
+
}
|
142
|
+
return 8;
|
143
|
+
}
|
144
|
+
|
145
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
146
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
147
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
148
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
149
|
+
|
150
|
+
/*
|
151
|
+
* Document-class: PG::BinaryEncoder::Timestamp < PG::SimpleEncoder
|
152
|
+
*
|
153
|
+
* This is a encoder class for conversion of Ruby Time objects to PostgreSQL binary timestamps.
|
154
|
+
*
|
155
|
+
* The following flags can be used to specify timezone interpretation:
|
156
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Send timestamp as UTC time (default)
|
157
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Send timestamp as local time (slower)
|
158
|
+
*
|
159
|
+
* Example:
|
160
|
+
* enco = PG::BinaryEncoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC)
|
161
|
+
* enco.encode(Time.utc(2000, 1, 1)) # => "\x00\x00\x00\x00\x00\x00\x00\x00"
|
162
|
+
*
|
163
|
+
* String values are expected to contain a binary data with a length of 8 byte.
|
164
|
+
*
|
165
|
+
*/
|
166
|
+
static int
|
167
|
+
pg_bin_enc_timestamp(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
168
|
+
{
|
169
|
+
if(out){
|
170
|
+
int64_t timestamp;
|
171
|
+
struct timespec ts;
|
172
|
+
|
173
|
+
/* second call -> write data to *out */
|
174
|
+
switch(TYPE(*intermediate)){
|
175
|
+
case T_STRING:
|
176
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
177
|
+
case T_TRUE:
|
178
|
+
write_nbo64(PG_INT64_MAX, out);
|
179
|
+
return 8;
|
180
|
+
case T_FALSE:
|
181
|
+
write_nbo64(PG_INT64_MIN, out);
|
182
|
+
return 8;
|
183
|
+
}
|
184
|
+
|
185
|
+
ts = rb_time_timespec(*intermediate);
|
186
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
187
|
+
* Adjust the 30 years difference. */
|
188
|
+
timestamp = (ts.tv_sec - 10957L * 24L * 3600L) * 1000000 + (ts.tv_nsec / 1000);
|
189
|
+
|
190
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
191
|
+
/* send as local time */
|
192
|
+
timestamp += NUM2LL(rb_funcall(*intermediate, rb_intern("utc_offset"), 0)) * 1000000;
|
193
|
+
}
|
194
|
+
|
195
|
+
write_nbo64(timestamp, out);
|
196
|
+
}else{
|
197
|
+
/* first call -> determine the required length */
|
198
|
+
if(TYPE(value) == T_STRING){
|
199
|
+
char *pstr = RSTRING_PTR(value);
|
200
|
+
if(RSTRING_LEN(value) >= 1){
|
201
|
+
switch(pstr[0]) {
|
202
|
+
case 'I':
|
203
|
+
case 'i':
|
204
|
+
*intermediate = Qtrue;
|
205
|
+
return 8;
|
206
|
+
case '-':
|
207
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
208
|
+
*intermediate = Qfalse;
|
209
|
+
return 8;
|
210
|
+
}
|
211
|
+
}
|
212
|
+
}
|
213
|
+
|
214
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
215
|
+
}
|
216
|
+
|
217
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
218
|
+
/* make a local time, so that utc_offset is set */
|
219
|
+
value = rb_funcall(value, rb_intern("getlocal"), 0);
|
220
|
+
}
|
221
|
+
*intermediate = value;
|
222
|
+
}
|
223
|
+
return 8;
|
224
|
+
}
|
225
|
+
|
226
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
227
|
+
int
|
228
|
+
date2j(int year, int month, int day)
|
229
|
+
{
|
230
|
+
int julian;
|
231
|
+
int century;
|
232
|
+
|
233
|
+
if (month > 2)
|
234
|
+
{
|
235
|
+
month += 1;
|
236
|
+
year += 4800;
|
237
|
+
}
|
238
|
+
else
|
239
|
+
{
|
240
|
+
month += 13;
|
241
|
+
year += 4799;
|
242
|
+
}
|
243
|
+
|
244
|
+
century = year / 100;
|
245
|
+
julian = year * 365 - 32167;
|
246
|
+
julian += year / 4 - century + century / 4;
|
247
|
+
julian += 7834 * month / 256 + day;
|
248
|
+
|
249
|
+
return julian;
|
250
|
+
} /* date2j() */
|
251
|
+
|
252
|
+
/*
|
253
|
+
* Document-class: PG::BinaryEncoder::Date < PG::SimpleEncoder
|
254
|
+
*
|
255
|
+
* This is a encoder class for conversion of Ruby Date objects to PostgreSQL binary date.
|
256
|
+
*
|
257
|
+
* String values are expected to contain a binary data with a length of 4 byte.
|
258
|
+
*
|
259
|
+
*/
|
260
|
+
static int
|
261
|
+
pg_bin_enc_date(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
262
|
+
{
|
263
|
+
if(out){
|
264
|
+
/* second call -> write data to *out */
|
265
|
+
switch(TYPE(*intermediate)){
|
266
|
+
case T_STRING:
|
267
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
268
|
+
case T_TRUE:
|
269
|
+
write_nbo32(PG_INT32_MAX, out);
|
270
|
+
return 4;
|
271
|
+
case T_FALSE:
|
272
|
+
write_nbo32(PG_INT32_MIN, out);
|
273
|
+
return 4;
|
274
|
+
}
|
275
|
+
|
276
|
+
VALUE year = rb_funcall(value, s_id_year, 0);
|
277
|
+
VALUE month = rb_funcall(value, s_id_month, 0);
|
278
|
+
VALUE day = rb_funcall(value, s_id_day, 0);
|
279
|
+
int jday = date2j(NUM2INT(year), NUM2INT(month), NUM2INT(day)) - POSTGRES_EPOCH_JDATE;
|
280
|
+
write_nbo32(jday, out);
|
281
|
+
|
282
|
+
}else{
|
283
|
+
/* first call -> determine the required length */
|
284
|
+
if(TYPE(value) == T_STRING){
|
285
|
+
char *pstr = RSTRING_PTR(value);
|
286
|
+
if(RSTRING_LEN(value) >= 1){
|
287
|
+
switch(pstr[0]) {
|
288
|
+
case 'I':
|
289
|
+
case 'i':
|
290
|
+
*intermediate = Qtrue;
|
291
|
+
return 4;
|
292
|
+
case '-':
|
293
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
294
|
+
*intermediate = Qfalse;
|
295
|
+
return 4;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
}
|
299
|
+
|
300
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
301
|
+
}
|
302
|
+
|
303
|
+
*intermediate = value;
|
304
|
+
}
|
305
|
+
return 4;
|
306
|
+
}
|
307
|
+
|
96
308
|
/*
|
97
309
|
* Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
|
98
310
|
*
|
@@ -141,6 +353,10 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
|
|
141
353
|
void
|
142
354
|
init_pg_binary_encoder(void)
|
143
355
|
{
|
356
|
+
s_id_year = rb_intern("year");
|
357
|
+
s_id_month = rb_intern("month");
|
358
|
+
s_id_day = rb_intern("day");
|
359
|
+
|
144
360
|
/* This module encapsulates all encoder classes with binary output format */
|
145
361
|
rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
|
146
362
|
|
@@ -153,10 +369,18 @@ init_pg_binary_encoder(void)
|
|
153
369
|
pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
154
370
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
|
155
371
|
pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
372
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float4", rb_cPG_SimpleEncoder ); */
|
373
|
+
pg_define_coder( "Float4", pg_bin_enc_float4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
374
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float8", rb_cPG_SimpleEncoder ); */
|
375
|
+
pg_define_coder( "Float8", pg_bin_enc_float8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
156
376
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
|
157
377
|
pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
158
378
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
|
159
379
|
pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
380
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Timestamp", rb_cPG_SimpleEncoder ); */
|
381
|
+
pg_define_coder( "Timestamp", pg_bin_enc_timestamp, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
382
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Date", rb_cPG_SimpleEncoder ); */
|
383
|
+
pg_define_coder( "Date", pg_bin_enc_date, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
160
384
|
|
161
385
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
|
162
386
|
pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
|
data/ext/pg_coder.c
CHANGED
@@ -35,7 +35,7 @@ pg_coder_init_encoder( VALUE self )
|
|
35
35
|
this->enc_func = NULL;
|
36
36
|
}
|
37
37
|
this->dec_func = NULL;
|
38
|
-
this->coder_obj
|
38
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
39
39
|
this->oid = 0;
|
40
40
|
this->format = 0;
|
41
41
|
this->flags = 0;
|
@@ -54,7 +54,7 @@ pg_coder_init_decoder( VALUE self )
|
|
54
54
|
} else {
|
55
55
|
this->dec_func = NULL;
|
56
56
|
}
|
57
|
-
this->coder_obj
|
57
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
58
58
|
this->oid = 0;
|
59
59
|
this->format = 0;
|
60
60
|
this->flags = 0;
|
@@ -99,7 +99,9 @@ const rb_data_type_t pg_coder_type = {
|
|
99
99
|
},
|
100
100
|
0,
|
101
101
|
0,
|
102
|
-
|
102
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
103
|
+
// macro to update VALUE references, as to trigger write barriers.
|
104
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
103
105
|
};
|
104
106
|
|
105
107
|
static VALUE
|
@@ -121,7 +123,7 @@ static const rb_data_type_t pg_composite_coder_type = {
|
|
121
123
|
},
|
122
124
|
&pg_coder_type,
|
123
125
|
0,
|
124
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
126
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
125
127
|
};
|
126
128
|
|
127
129
|
static VALUE
|
@@ -273,6 +275,7 @@ static VALUE
|
|
273
275
|
pg_coder_oid_set(VALUE self, VALUE oid)
|
274
276
|
{
|
275
277
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
278
|
+
rb_check_frozen(self);
|
276
279
|
this->oid = NUM2UINT(oid);
|
277
280
|
return oid;
|
278
281
|
}
|
@@ -304,6 +307,7 @@ static VALUE
|
|
304
307
|
pg_coder_format_set(VALUE self, VALUE format)
|
305
308
|
{
|
306
309
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
310
|
+
rb_check_frozen(self);
|
307
311
|
this->format = NUM2INT(format);
|
308
312
|
return format;
|
309
313
|
}
|
@@ -335,6 +339,7 @@ static VALUE
|
|
335
339
|
pg_coder_flags_set(VALUE self, VALUE flags)
|
336
340
|
{
|
337
341
|
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
342
|
+
rb_check_frozen(self);
|
338
343
|
this->flags = NUM2INT(flags);
|
339
344
|
return flags;
|
340
345
|
}
|
@@ -366,6 +371,7 @@ static VALUE
|
|
366
371
|
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
367
372
|
{
|
368
373
|
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
374
|
+
rb_check_frozen(self);
|
369
375
|
this->needs_quotation = RTEST(needs_quotation);
|
370
376
|
return needs_quotation;
|
371
377
|
}
|
@@ -396,6 +402,7 @@ static VALUE
|
|
396
402
|
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
397
403
|
{
|
398
404
|
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
405
|
+
rb_check_frozen(self);
|
399
406
|
StringValue(delimiter);
|
400
407
|
if(RSTRING_LEN(delimiter) != 1)
|
401
408
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
@@ -430,6 +437,7 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
430
437
|
{
|
431
438
|
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
|
432
439
|
|
440
|
+
rb_check_frozen(self);
|
433
441
|
if ( NIL_P(elem_type) ){
|
434
442
|
this->elem = NULL;
|
435
443
|
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
|
@@ -452,10 +460,10 @@ static const rb_data_type_t pg_coder_cfunc_type = {
|
|
452
460
|
},
|
453
461
|
0,
|
454
462
|
0,
|
455
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
463
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
456
464
|
};
|
457
465
|
|
458
|
-
|
466
|
+
VALUE
|
459
467
|
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
460
468
|
{
|
461
469
|
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
|
@@ -468,9 +476,10 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
468
476
|
if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
|
469
477
|
rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
|
470
478
|
|
471
|
-
rb_define_const( coder_klass, "CFUNC", cfunc_obj );
|
479
|
+
rb_define_const( coder_klass, "CFUNC", rb_obj_freeze(cfunc_obj) );
|
472
480
|
|
473
481
|
RB_GC_GUARD(cfunc_obj);
|
482
|
+
return coder_klass;
|
474
483
|
}
|
475
484
|
|
476
485
|
|
data/ext/pg_connection.c
CHANGED
@@ -16,9 +16,6 @@ static ID s_id_autoclose_set;
|
|
16
16
|
static VALUE sym_type, sym_format, sym_value;
|
17
17
|
static VALUE sym_symbol, sym_string, sym_static_symbol;
|
18
18
|
|
19
|
-
static PQnoticeReceiver default_notice_receiver = NULL;
|
20
|
-
static PQnoticeProcessor default_notice_processor = NULL;
|
21
|
-
|
22
19
|
static VALUE pgconn_finish( VALUE );
|
23
20
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
24
21
|
static VALUE pgconn_wait_for_flush( VALUE self );
|
@@ -117,7 +114,7 @@ pgconn_close_socket_io( VALUE self )
|
|
117
114
|
rb_funcall( socket_io, rb_intern("close"), 0 );
|
118
115
|
}
|
119
116
|
|
120
|
-
this->socket_io
|
117
|
+
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
121
118
|
}
|
122
119
|
|
123
120
|
|
@@ -237,7 +234,7 @@ static const rb_data_type_t pg_connection_type = {
|
|
237
234
|
},
|
238
235
|
0,
|
239
236
|
0,
|
240
|
-
|
237
|
+
RUBY_TYPED_WB_PROTECTED,
|
241
238
|
};
|
242
239
|
|
243
240
|
|
@@ -258,14 +255,14 @@ pgconn_s_allocate( VALUE klass )
|
|
258
255
|
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
259
256
|
|
260
257
|
this->pgconn = NULL;
|
261
|
-
this->socket_io
|
262
|
-
this->notice_receiver
|
263
|
-
this->notice_processor
|
264
|
-
this->type_map_for_queries
|
265
|
-
this->type_map_for_results
|
266
|
-
this->encoder_for_put_copy_data
|
267
|
-
this->decoder_for_get_copy_data
|
268
|
-
this->trace_stream
|
258
|
+
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
259
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
|
260
|
+
RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
|
261
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
|
262
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
|
263
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
|
264
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
|
265
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
269
266
|
rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
|
270
267
|
|
271
268
|
return self;
|
@@ -766,6 +763,10 @@ pgconn_conninfo( VALUE self )
|
|
766
763
|
*
|
767
764
|
* ... and other constants of kind PG::Constants::CONNECTION_*
|
768
765
|
*
|
766
|
+
* This method returns the status of the last command from memory.
|
767
|
+
* It doesn't do any socket access hence is not suitable to test the connectivity.
|
768
|
+
* See check_socket for a way to verify the socket state.
|
769
|
+
*
|
769
770
|
* Example:
|
770
771
|
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
771
772
|
*/
|
@@ -941,7 +942,7 @@ pgconn_socket_io(VALUE self)
|
|
941
942
|
/* Disable autoclose feature */
|
942
943
|
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
943
944
|
|
944
|
-
this->socket_io
|
945
|
+
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
945
946
|
}
|
946
947
|
|
947
948
|
return socket_io;
|
@@ -1158,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1158
1159
|
},
|
1159
1160
|
0,
|
1160
1161
|
0,
|
1161
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1162
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1162
1163
|
};
|
1163
1164
|
|
1164
1165
|
static char *
|
@@ -1191,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1191
1192
|
},
|
1192
1193
|
0,
|
1193
1194
|
0,
|
1194
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1195
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1195
1196
|
};
|
1196
1197
|
|
1197
1198
|
static int
|
@@ -1814,6 +1815,7 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1814
1815
|
{
|
1815
1816
|
PGconn *conn = pg_get_pgconn(self);
|
1816
1817
|
|
1818
|
+
rb_check_frozen(self);
|
1817
1819
|
if( PQsetSingleRowMode(conn) == 0 )
|
1818
1820
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
1819
1821
|
|
@@ -2148,6 +2150,7 @@ pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
2148
2150
|
{
|
2149
2151
|
int arg;
|
2150
2152
|
PGconn *conn = pg_get_pgconn(self);
|
2153
|
+
rb_check_frozen(self);
|
2151
2154
|
if(state == Qtrue)
|
2152
2155
|
arg = 1;
|
2153
2156
|
else if (state == Qfalse)
|
@@ -2464,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
2464
2467
|
static VALUE
|
2465
2468
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2466
2469
|
t_pg_connection *conn = pg_get_connection(self);
|
2470
|
+
rb_check_frozen(self);
|
2467
2471
|
conn->flush_data = RTEST(enabled);
|
2468
2472
|
return enabled;
|
2469
2473
|
}
|
@@ -2718,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2718
2722
|
VALUE new_file;
|
2719
2723
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2720
2724
|
|
2725
|
+
rb_check_frozen(self);
|
2721
2726
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2722
2727
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2723
2728
|
|
@@ -2739,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2739
2744
|
rb_raise(rb_eArgError, "stream is not writable");
|
2740
2745
|
|
2741
2746
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2742
|
-
this->trace_stream
|
2747
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
2743
2748
|
|
2744
2749
|
PQtrace(this->pgconn, new_fp);
|
2745
2750
|
return Qnil;
|
@@ -2758,7 +2763,7 @@ pgconn_untrace(VALUE self)
|
|
2758
2763
|
|
2759
2764
|
PQuntrace(this->pgconn);
|
2760
2765
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
2761
|
-
this->trace_stream
|
2766
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
2762
2767
|
return Qnil;
|
2763
2768
|
}
|
2764
2769
|
|
@@ -2817,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2817
2822
|
VALUE proc, old_proc;
|
2818
2823
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2819
2824
|
|
2825
|
+
rb_check_frozen(self);
|
2820
2826
|
/* If default_notice_receiver is unset, assume that the current
|
2821
2827
|
* notice receiver is the default, and save it to a global variable.
|
2822
2828
|
* This should not be a problem because the default receiver is
|
2823
2829
|
* always the same, so won't vary among connections.
|
2824
2830
|
*/
|
2825
|
-
if(default_notice_receiver == NULL)
|
2826
|
-
default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2831
|
+
if(this->default_notice_receiver == NULL)
|
2832
|
+
this->default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2827
2833
|
|
2828
2834
|
old_proc = this->notice_receiver;
|
2829
2835
|
if( rb_block_given_p() ) {
|
@@ -2832,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2832
2838
|
} else {
|
2833
2839
|
/* if no block is given, set back to default */
|
2834
2840
|
proc = Qnil;
|
2835
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
2841
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
2836
2842
|
}
|
2837
2843
|
|
2838
|
-
this->notice_receiver
|
2844
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
2839
2845
|
return old_proc;
|
2840
2846
|
}
|
2841
2847
|
|
@@ -2850,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2850
2856
|
VALUE self = (VALUE)arg;
|
2851
2857
|
t_pg_connection *this = pg_get_connection( self );
|
2852
2858
|
|
2853
|
-
if (this->
|
2859
|
+
if (this->notice_processor != Qnil) {
|
2854
2860
|
VALUE message_str = rb_str_new2(message);
|
2855
2861
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2856
|
-
rb_funcall(this->
|
2862
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
2857
2863
|
}
|
2858
2864
|
return;
|
2859
2865
|
}
|
@@ -2877,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
2877
2883
|
VALUE proc, old_proc;
|
2878
2884
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2879
2885
|
|
2886
|
+
rb_check_frozen(self);
|
2880
2887
|
/* If default_notice_processor is unset, assume that the current
|
2881
2888
|
* notice processor is the default, and save it to a global variable.
|
2882
2889
|
* This should not be a problem because the default processor is
|
2883
2890
|
* always the same, so won't vary among connections.
|
2884
2891
|
*/
|
2885
|
-
if(default_notice_processor == NULL)
|
2886
|
-
default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
2892
|
+
if(this->default_notice_processor == NULL)
|
2893
|
+
this->default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
2887
2894
|
|
2888
|
-
old_proc = this->
|
2895
|
+
old_proc = this->notice_processor;
|
2889
2896
|
if( rb_block_given_p() ) {
|
2890
2897
|
proc = rb_block_proc();
|
2891
2898
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
2892
2899
|
} else {
|
2893
2900
|
/* if no block is given, set back to default */
|
2894
2901
|
proc = Qnil;
|
2895
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
2902
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
2896
2903
|
}
|
2897
2904
|
|
2898
|
-
this->
|
2905
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
2899
2906
|
return old_proc;
|
2900
2907
|
}
|
2901
2908
|
|
@@ -2927,6 +2934,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2927
2934
|
{
|
2928
2935
|
PGconn *conn = pg_get_pgconn( self );
|
2929
2936
|
|
2937
|
+
rb_check_frozen(self);
|
2930
2938
|
Check_Type(str, T_STRING);
|
2931
2939
|
|
2932
2940
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
@@ -3095,7 +3103,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3095
3103
|
VALUE rb_pgresult = Qnil;
|
3096
3104
|
PGresult *cur, *prev;
|
3097
3105
|
|
3098
|
-
|
3106
|
+
cur = prev = NULL;
|
3099
3107
|
for(;;) {
|
3100
3108
|
int status;
|
3101
3109
|
|
@@ -4058,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
4058
4066
|
static VALUE
|
4059
4067
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
4060
4068
|
{
|
4069
|
+
rb_check_frozen(self);
|
4061
4070
|
if (NIL_P(enc)) {
|
4062
4071
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
4063
4072
|
return enc;
|
@@ -4112,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4112
4121
|
{
|
4113
4122
|
VALUE query_format, query;
|
4114
4123
|
|
4124
|
+
rb_check_frozen(self);
|
4115
4125
|
Check_Type(encname, T_STRING);
|
4116
4126
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4117
4127
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
@@ -4164,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
4164
4174
|
rb_encoding *enc;
|
4165
4175
|
const char *encname;
|
4166
4176
|
|
4177
|
+
rb_check_frozen(self);
|
4167
4178
|
if (( enc = rb_default_internal_encoding() )) {
|
4168
4179
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
4169
4180
|
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
@@ -4193,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
4193
4204
|
t_typemap *tm;
|
4194
4205
|
UNUSED(tm);
|
4195
4206
|
|
4207
|
+
rb_check_frozen(self);
|
4196
4208
|
/* Check type of method param */
|
4197
4209
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4198
4210
|
|
4199
|
-
this->type_map_for_queries
|
4211
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
4200
4212
|
|
4201
4213
|
return typemap;
|
4202
4214
|
}
|
@@ -4233,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
4233
4245
|
t_typemap *tm;
|
4234
4246
|
UNUSED(tm);
|
4235
4247
|
|
4248
|
+
rb_check_frozen(self);
|
4236
4249
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4237
|
-
this->type_map_for_results
|
4250
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
4238
4251
|
|
4239
4252
|
return typemap;
|
4240
4253
|
}
|
@@ -4272,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4272
4285
|
{
|
4273
4286
|
t_pg_connection *this = pg_get_connection( self );
|
4274
4287
|
|
4288
|
+
rb_check_frozen(self);
|
4275
4289
|
if( encoder != Qnil ){
|
4276
4290
|
t_pg_coder *co;
|
4277
4291
|
UNUSED(co);
|
4278
4292
|
/* Check argument type */
|
4279
4293
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4280
4294
|
}
|
4281
|
-
this->encoder_for_put_copy_data
|
4295
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
4282
4296
|
|
4283
4297
|
return encoder;
|
4284
4298
|
}
|
@@ -4320,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4320
4334
|
{
|
4321
4335
|
t_pg_connection *this = pg_get_connection( self );
|
4322
4336
|
|
4337
|
+
rb_check_frozen(self);
|
4323
4338
|
if( decoder != Qnil ){
|
4324
4339
|
t_pg_coder *co;
|
4325
4340
|
UNUSED(co);
|
4326
4341
|
/* Check argument type */
|
4327
4342
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4328
4343
|
}
|
4329
|
-
this->decoder_for_get_copy_data
|
4344
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
4330
4345
|
|
4331
4346
|
return decoder;
|
4332
4347
|
}
|
@@ -4372,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
4372
4387
|
{
|
4373
4388
|
t_pg_connection *this = pg_get_connection( self );
|
4374
4389
|
|
4390
|
+
rb_check_frozen(self);
|
4375
4391
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4376
4392
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4377
4393
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|