pg 1.4.6-x86-mingw32 → 1.5.0-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 +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/3.1/pg_ext.so +0 -0
- data/lib/3.2/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/x86-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;
|