pg 0.18.4 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/BSDL +2 -2
- data/ChangeLog +0 -5911
- data/History.rdoc +240 -0
- data/Manifest.txt +8 -20
- data/README-Windows.rdoc +4 -4
- data/README.ja.rdoc +1 -2
- data/README.rdoc +64 -15
- data/Rakefile +20 -21
- data/Rakefile.cross +67 -69
- data/ext/errorcodes.def +101 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +33 -2
- data/ext/extconf.rb +26 -36
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +156 -145
- data/ext/pg.h +74 -98
- data/ext/pg_binary_decoder.c +82 -15
- data/ext/pg_binary_encoder.c +20 -19
- data/ext/pg_coder.c +103 -21
- data/ext/pg_connection.c +917 -523
- data/ext/pg_copy_coder.c +50 -12
- data/ext/pg_record_coder.c +491 -0
- data/ext/pg_result.c +590 -208
- data/ext/pg_text_decoder.c +606 -40
- data/ext/pg_text_encoder.c +245 -94
- data/ext/pg_tuple.c +549 -0
- data/ext/pg_type_map.c +14 -7
- data/ext/pg_type_map_all_strings.c +4 -4
- data/ext/pg_type_map_by_class.c +9 -4
- data/ext/pg_type_map_by_column.c +7 -6
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -2
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/{util.c → pg_util.c} +10 -10
- data/ext/{util.h → pg_util.h} +2 -2
- data/lib/pg.rb +23 -13
- data/lib/pg/basic_type_mapping.rb +155 -32
- data/lib/pg/binary_decoder.rb +23 -0
- data/lib/pg/coder.rb +23 -2
- data/lib/pg/connection.rb +73 -13
- data/lib/pg/constants.rb +2 -1
- data/lib/pg/exceptions.rb +2 -1
- data/lib/pg/result.rb +24 -7
- data/lib/pg/text_decoder.rb +24 -22
- data/lib/pg/text_encoder.rb +40 -8
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +3 -2
- data/spec/helpers.rb +61 -36
- data/spec/pg/basic_type_mapping_spec.rb +415 -36
- data/spec/pg/connection_spec.rb +732 -327
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +253 -21
- data/spec/pg/tuple_spec.rb +333 -0
- data/spec/pg/type_map_by_class_spec.rb +4 -4
- data/spec/pg/type_map_by_column_spec.rb +6 -2
- data/spec/pg/type_map_by_mri_type_spec.rb +2 -2
- data/spec/pg/type_map_by_oid_spec.rb +3 -3
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +446 -20
- data/spec/pg_spec.rb +2 -2
- metadata +63 -72
- metadata.gz.sig +0 -0
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -186
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -294
- data/sample/replication_monitor.rb +0 -231
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -320
data/ext/pg_binary_encoder.c
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
7
|
#include "pg.h"
|
8
|
-
#include "
|
8
|
+
#include "pg_util.h"
|
9
9
|
#ifdef HAVE_INTTYPES_H
|
10
10
|
#include <inttypes.h>
|
11
11
|
#endif
|
@@ -22,14 +22,15 @@ VALUE rb_mPG_BinaryEncoder;
|
|
22
22
|
*
|
23
23
|
*/
|
24
24
|
static int
|
25
|
-
pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
25
|
+
pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
26
26
|
{
|
27
27
|
char mybool;
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
if (value == Qtrue) {
|
29
|
+
mybool = 1;
|
30
|
+
} else if (value == Qfalse) {
|
31
|
+
mybool = 0;
|
32
|
+
} else {
|
33
|
+
rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
|
33
34
|
}
|
34
35
|
if(out) *out = mybool;
|
35
36
|
return 1;
|
@@ -38,13 +39,13 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
38
39
|
/*
|
39
40
|
* Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
|
40
41
|
*
|
41
|
-
* This is the encoder class for the PostgreSQL int2 type.
|
42
|
+
* This is the encoder class for the PostgreSQL +int2+ (alias +smallint+) type.
|
42
43
|
*
|
43
44
|
* Non-Number values are expected to have method +to_i+ defined.
|
44
45
|
*
|
45
46
|
*/
|
46
47
|
static int
|
47
|
-
pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
48
|
+
pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
48
49
|
{
|
49
50
|
if(out){
|
50
51
|
write_nbo16(NUM2INT(*intermediate), out);
|
@@ -55,15 +56,15 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
55
56
|
}
|
56
57
|
|
57
58
|
/*
|
58
|
-
* Document-class: PG::BinaryEncoder::
|
59
|
+
* Document-class: PG::BinaryEncoder::Int4 < PG::SimpleEncoder
|
59
60
|
*
|
60
|
-
* This is the encoder class for the PostgreSQL int4 type.
|
61
|
+
* This is the encoder class for the PostgreSQL +int4+ (alias +integer+) type.
|
61
62
|
*
|
62
63
|
* Non-Number values are expected to have method +to_i+ defined.
|
63
64
|
*
|
64
65
|
*/
|
65
66
|
static int
|
66
|
-
pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
67
|
+
pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
67
68
|
{
|
68
69
|
if(out){
|
69
70
|
write_nbo32(NUM2LONG(*intermediate), out);
|
@@ -74,15 +75,15 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
74
75
|
}
|
75
76
|
|
76
77
|
/*
|
77
|
-
* Document-class: PG::BinaryEncoder::
|
78
|
+
* Document-class: PG::BinaryEncoder::Int8 < PG::SimpleEncoder
|
78
79
|
*
|
79
|
-
* This is the encoder class for the PostgreSQL int8 type.
|
80
|
+
* This is the encoder class for the PostgreSQL +int8+ (alias +bigint+) type.
|
80
81
|
*
|
81
82
|
* Non-Number values are expected to have method +to_i+ defined.
|
82
83
|
*
|
83
84
|
*/
|
84
85
|
static int
|
85
|
-
pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
86
|
+
pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
86
87
|
{
|
87
88
|
if(out){
|
88
89
|
write_nbo64(NUM2LL(*intermediate), out);
|
@@ -100,7 +101,7 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
|
100
101
|
*
|
101
102
|
*/
|
102
103
|
static int
|
103
|
-
pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
104
|
+
pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
104
105
|
{
|
105
106
|
int strlen;
|
106
107
|
VALUE subint;
|
@@ -109,13 +110,13 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
|
|
109
110
|
|
110
111
|
if(out){
|
111
112
|
/* Second encoder pass, if required */
|
112
|
-
strlen = enc_func(this->elem, value, out, intermediate);
|
113
|
+
strlen = enc_func(this->elem, value, out, intermediate, enc_idx);
|
113
114
|
strlen = base64_decode( out, out, strlen );
|
114
115
|
|
115
116
|
return strlen;
|
116
117
|
} else {
|
117
118
|
/* First encoder pass */
|
118
|
-
strlen = enc_func(this->elem, value, NULL, &subint);
|
119
|
+
strlen = enc_func(this->elem, value, NULL, &subint, enc_idx);
|
119
120
|
|
120
121
|
if( strlen == -1 ){
|
121
122
|
/* Encoded string is returned in subint */
|
data/ext/pg_coder.c
CHANGED
@@ -38,6 +38,7 @@ pg_coder_init_encoder( VALUE self )
|
|
38
38
|
this->coder_obj = self;
|
39
39
|
this->oid = 0;
|
40
40
|
this->format = 0;
|
41
|
+
this->flags = 0;
|
41
42
|
rb_iv_set( self, "@name", Qnil );
|
42
43
|
}
|
43
44
|
|
@@ -56,14 +57,27 @@ pg_coder_init_decoder( VALUE self )
|
|
56
57
|
this->coder_obj = self;
|
57
58
|
this->oid = 0;
|
58
59
|
this->format = 0;
|
60
|
+
this->flags = 0;
|
59
61
|
rb_iv_set( self, "@name", Qnil );
|
60
62
|
}
|
61
63
|
|
64
|
+
void
|
65
|
+
pg_coder_mark(t_pg_coder *this)
|
66
|
+
{
|
67
|
+
rb_gc_mark(this->coder_obj);
|
68
|
+
}
|
69
|
+
|
70
|
+
static void
|
71
|
+
pg_composite_coder_mark(t_pg_composite_coder *this)
|
72
|
+
{
|
73
|
+
pg_coder_mark(&this->comp);
|
74
|
+
}
|
75
|
+
|
62
76
|
static VALUE
|
63
77
|
pg_simple_encoder_allocate( VALUE klass )
|
64
78
|
{
|
65
79
|
t_pg_coder *this;
|
66
|
-
VALUE self = Data_Make_Struct( klass, t_pg_coder,
|
80
|
+
VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
|
67
81
|
pg_coder_init_encoder( self );
|
68
82
|
return self;
|
69
83
|
}
|
@@ -72,7 +86,7 @@ static VALUE
|
|
72
86
|
pg_composite_encoder_allocate( VALUE klass )
|
73
87
|
{
|
74
88
|
t_pg_composite_coder *this;
|
75
|
-
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder,
|
89
|
+
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
|
76
90
|
pg_coder_init_encoder( self );
|
77
91
|
this->elem = NULL;
|
78
92
|
this->needs_quotation = 1;
|
@@ -85,7 +99,7 @@ static VALUE
|
|
85
99
|
pg_simple_decoder_allocate( VALUE klass )
|
86
100
|
{
|
87
101
|
t_pg_coder *this;
|
88
|
-
VALUE self = Data_Make_Struct( klass, t_pg_coder,
|
102
|
+
VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
|
89
103
|
pg_coder_init_decoder( self );
|
90
104
|
return self;
|
91
105
|
}
|
@@ -94,7 +108,7 @@ static VALUE
|
|
94
108
|
pg_composite_decoder_allocate( VALUE klass )
|
95
109
|
{
|
96
110
|
t_pg_composite_coder *this;
|
97
|
-
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder,
|
111
|
+
VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
|
98
112
|
pg_coder_init_decoder( self );
|
99
113
|
this->elem = NULL;
|
100
114
|
this->needs_quotation = 1;
|
@@ -105,7 +119,7 @@ pg_composite_decoder_allocate( VALUE klass )
|
|
105
119
|
|
106
120
|
/*
|
107
121
|
* call-seq:
|
108
|
-
* coder.encode( value )
|
122
|
+
* coder.encode( value [, encoding] )
|
109
123
|
*
|
110
124
|
* Encodes the given Ruby object into string representation, without
|
111
125
|
* sending data to/from the database server.
|
@@ -114,13 +128,24 @@ pg_composite_decoder_allocate( VALUE klass )
|
|
114
128
|
*
|
115
129
|
*/
|
116
130
|
static VALUE
|
117
|
-
pg_coder_encode(VALUE
|
131
|
+
pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
118
132
|
{
|
119
133
|
VALUE res;
|
120
134
|
VALUE intermediate;
|
135
|
+
VALUE value;
|
121
136
|
int len, len2;
|
137
|
+
int enc_idx;
|
122
138
|
t_pg_coder *this = DATA_PTR(self);
|
123
139
|
|
140
|
+
if(argc < 1 || argc > 2){
|
141
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
|
142
|
+
}else if(argc == 1){
|
143
|
+
enc_idx = rb_ascii8bit_encindex();
|
144
|
+
}else{
|
145
|
+
enc_idx = rb_to_encoding_index(argv[1]);
|
146
|
+
}
|
147
|
+
value = argv[0];
|
148
|
+
|
124
149
|
if( NIL_P(value) )
|
125
150
|
return Qnil;
|
126
151
|
|
@@ -128,22 +153,21 @@ pg_coder_encode(VALUE self, VALUE value)
|
|
128
153
|
rb_raise(rb_eRuntimeError, "no encoder function defined");
|
129
154
|
}
|
130
155
|
|
131
|
-
len = this->enc_func( this, value, NULL, &intermediate );
|
156
|
+
len = this->enc_func( this, value, NULL, &intermediate, enc_idx );
|
132
157
|
|
133
158
|
if( len == -1 ){
|
134
159
|
/* The intermediate value is a String that can be used directly. */
|
135
|
-
OBJ_INFECT(intermediate, value);
|
136
160
|
return intermediate;
|
137
161
|
}
|
138
162
|
|
139
163
|
res = rb_str_new(NULL, len);
|
140
|
-
|
164
|
+
PG_ENCODING_SET_NOCHECK(res, enc_idx);
|
165
|
+
len2 = this->enc_func( this, value, RSTRING_PTR(res), &intermediate, enc_idx );
|
141
166
|
if( len < len2 ){
|
142
167
|
rb_bug("%s: result length of first encoder run (%i) is less than second run (%i)",
|
143
168
|
rb_obj_classname( self ), len, len2 );
|
144
169
|
}
|
145
170
|
rb_str_set_len( res, len2 );
|
146
|
-
OBJ_INFECT(res, value);
|
147
171
|
|
148
172
|
RB_GC_GUARD(intermediate);
|
149
173
|
|
@@ -165,8 +189,8 @@ static VALUE
|
|
165
189
|
pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
166
190
|
{
|
167
191
|
char *val;
|
168
|
-
|
169
|
-
|
192
|
+
int tuple = -1;
|
193
|
+
int field = -1;
|
170
194
|
VALUE res;
|
171
195
|
t_pg_coder *this = DATA_PTR(self);
|
172
196
|
|
@@ -180,13 +204,16 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
180
204
|
if( NIL_P(argv[0]) )
|
181
205
|
return Qnil;
|
182
206
|
|
183
|
-
|
207
|
+
if( this->format == 0 ){
|
208
|
+
val = StringValueCStr(argv[0]);
|
209
|
+
}else{
|
210
|
+
val = StringValuePtr(argv[0]);
|
211
|
+
}
|
184
212
|
if( !this->dec_func ){
|
185
213
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
186
214
|
}
|
187
215
|
|
188
216
|
res = this->dec_func(this, val, RSTRING_LEN(argv[0]), tuple, field, ENCODING_GET(argv[0]));
|
189
|
-
OBJ_INFECT(res, argv[0]);
|
190
217
|
|
191
218
|
return res;
|
192
219
|
}
|
@@ -253,6 +280,36 @@ pg_coder_format_get(VALUE self)
|
|
253
280
|
return INT2NUM(this->format);
|
254
281
|
}
|
255
282
|
|
283
|
+
/*
|
284
|
+
* call-seq:
|
285
|
+
* coder.flags = Integer
|
286
|
+
*
|
287
|
+
* Set coder specific bitwise OR-ed flags.
|
288
|
+
* See the particular en- or decoder description for available flags.
|
289
|
+
*
|
290
|
+
* The default is +0+.
|
291
|
+
*/
|
292
|
+
static VALUE
|
293
|
+
pg_coder_flags_set(VALUE self, VALUE flags)
|
294
|
+
{
|
295
|
+
t_pg_coder *this = DATA_PTR(self);
|
296
|
+
this->flags = NUM2INT(flags);
|
297
|
+
return flags;
|
298
|
+
}
|
299
|
+
|
300
|
+
/*
|
301
|
+
* call-seq:
|
302
|
+
* coder.flags -> Integer
|
303
|
+
*
|
304
|
+
* Get current bitwise OR-ed coder flags.
|
305
|
+
*/
|
306
|
+
static VALUE
|
307
|
+
pg_coder_flags_get(VALUE self)
|
308
|
+
{
|
309
|
+
t_pg_coder *this = DATA_PTR(self);
|
310
|
+
return INT2NUM(this->flags);
|
311
|
+
}
|
312
|
+
|
256
313
|
/*
|
257
314
|
* call-seq:
|
258
315
|
* coder.needs_quotation = Boolean
|
@@ -352,6 +409,11 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
352
409
|
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
|
353
410
|
rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
|
354
411
|
|
412
|
+
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_TextEncoder )
|
413
|
+
rb_define_method( coder_klass, "encode", pg_coder_encode, -1 );
|
414
|
+
if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
|
415
|
+
rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
|
416
|
+
|
355
417
|
rb_define_const( coder_klass, "CFUNC", cfunc_obj );
|
356
418
|
|
357
419
|
RB_GC_GUARD(cfunc_obj);
|
@@ -359,10 +421,19 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
359
421
|
|
360
422
|
|
361
423
|
static int
|
362
|
-
pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
|
424
|
+
pg_text_enc_in_ruby(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
363
425
|
{
|
364
|
-
|
365
|
-
|
426
|
+
int arity = rb_obj_method_arity(conv->coder_obj, s_id_encode);
|
427
|
+
if( arity == 1 ){
|
428
|
+
VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 1, value );
|
429
|
+
StringValue( out_str );
|
430
|
+
*intermediate = rb_str_export_to_enc(out_str, rb_enc_from_index(enc_idx));
|
431
|
+
}else{
|
432
|
+
VALUE enc = rb_enc_from_encoding(rb_enc_from_index(enc_idx));
|
433
|
+
VALUE out_str = rb_funcall( conv->coder_obj, s_id_encode, 2, value, enc );
|
434
|
+
StringValue( out_str );
|
435
|
+
*intermediate = out_str;
|
436
|
+
}
|
366
437
|
return -1;
|
367
438
|
}
|
368
439
|
|
@@ -382,14 +453,14 @@ pg_coder_enc_func(t_pg_coder *this)
|
|
382
453
|
}
|
383
454
|
|
384
455
|
static VALUE
|
385
|
-
pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
456
|
+
pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
386
457
|
{
|
387
458
|
VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
|
388
459
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
389
460
|
}
|
390
461
|
|
391
462
|
static VALUE
|
392
|
-
pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
463
|
+
pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
393
464
|
{
|
394
465
|
VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
|
395
466
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
@@ -436,14 +507,25 @@ init_pg_coder()
|
|
436
507
|
rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
|
437
508
|
rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
|
438
509
|
rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
|
510
|
+
rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
|
511
|
+
rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
|
512
|
+
|
513
|
+
/* define flags to be used with PG::Coder#flags= */
|
514
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
|
515
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
|
516
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
|
517
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
|
518
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
|
519
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
|
520
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
|
521
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
|
522
|
+
|
439
523
|
/*
|
440
524
|
* Name of the coder or the corresponding data type.
|
441
525
|
*
|
442
526
|
* This accessor is only used in PG::Coder#inspect .
|
443
527
|
*/
|
444
528
|
rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
|
445
|
-
rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, 1 );
|
446
|
-
rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
|
447
529
|
|
448
530
|
/* Document-class: PG::SimpleCoder < PG::Coder */
|
449
531
|
rb_cPG_SimpleCoder = rb_define_class_under( rb_mPG, "SimpleCoder", rb_cPG_Coder );
|
data/ext/pg_connection.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg_connection.c - PG::Connection class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
@@ -13,24 +13,14 @@
|
|
13
13
|
VALUE rb_cPGconn;
|
14
14
|
static ID s_id_encode;
|
15
15
|
static VALUE sym_type, sym_format, sym_value;
|
16
|
+
static VALUE sym_symbol, sym_string, sym_static_symbol;
|
16
17
|
|
17
18
|
static PQnoticeReceiver default_notice_receiver = NULL;
|
18
19
|
static PQnoticeProcessor default_notice_processor = NULL;
|
19
20
|
|
20
21
|
static VALUE pgconn_finish( VALUE );
|
21
|
-
#ifdef M17N_SUPPORTED
|
22
22
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
23
|
-
void pgconn_set_internal_encoding_index( VALUE );
|
24
|
-
#endif
|
25
|
-
|
26
|
-
#ifndef HAVE_RB_THREAD_FD_SELECT
|
27
|
-
#define rb_fdset_t fd_set
|
28
|
-
#define rb_fd_init(f)
|
29
|
-
#define rb_fd_zero(f) FD_ZERO(f)
|
30
|
-
#define rb_fd_set(n, f) FD_SET(n, f)
|
31
|
-
#define rb_fd_term(f)
|
32
|
-
#define rb_thread_fd_select rb_thread_select
|
33
|
-
#endif
|
23
|
+
static void pgconn_set_internal_encoding_index( VALUE );
|
34
24
|
|
35
25
|
/*
|
36
26
|
* Global functions
|
@@ -52,7 +42,7 @@ pg_get_connection( VALUE self )
|
|
52
42
|
* Fetch the PG::Connection object data pointer and check it's
|
53
43
|
* PGconn data pointer for sanity.
|
54
44
|
*/
|
55
|
-
t_pg_connection *
|
45
|
+
static t_pg_connection *
|
56
46
|
pg_get_connection_safe( VALUE self )
|
57
47
|
{
|
58
48
|
t_pg_connection *this;
|
@@ -88,16 +78,15 @@ pg_get_pgconn( VALUE self )
|
|
88
78
|
/*
|
89
79
|
* Close the associated socket IO object if there is one.
|
90
80
|
*/
|
91
|
-
void
|
81
|
+
static void
|
92
82
|
pgconn_close_socket_io( VALUE self )
|
93
83
|
{
|
94
84
|
t_pg_connection *this = pg_get_connection( self );
|
95
85
|
VALUE socket_io = this->socket_io;
|
96
86
|
|
97
87
|
if ( RTEST(socket_io) ) {
|
98
|
-
#if defined(_WIN32)
|
99
|
-
|
100
|
-
if( rb_w32_unwrap_io_handle(ruby_sd) ){
|
88
|
+
#if defined(_WIN32)
|
89
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
101
90
|
rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
|
102
91
|
}
|
103
92
|
#endif
|
@@ -141,6 +130,16 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
|
|
141
130
|
return ary;
|
142
131
|
}
|
143
132
|
|
133
|
+
static const char *pg_cstr_enc(VALUE str, int enc_idx){
|
134
|
+
const char *ptr = StringValueCStr(str);
|
135
|
+
if( ENCODING_GET(str) == enc_idx ){
|
136
|
+
return ptr;
|
137
|
+
} else {
|
138
|
+
str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
|
139
|
+
return StringValueCStr(str);
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
144
143
|
|
145
144
|
/*
|
146
145
|
* GC Mark function
|
@@ -154,7 +153,6 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
154
153
|
rb_gc_mark( this->type_map_for_queries );
|
155
154
|
rb_gc_mark( this->type_map_for_results );
|
156
155
|
rb_gc_mark( this->trace_stream );
|
157
|
-
rb_gc_mark( this->external_encoding );
|
158
156
|
rb_gc_mark( this->encoder_for_put_copy_data );
|
159
157
|
rb_gc_mark( this->decoder_for_get_copy_data );
|
160
158
|
}
|
@@ -166,6 +164,10 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
166
164
|
static void
|
167
165
|
pgconn_gc_free( t_pg_connection *this )
|
168
166
|
{
|
167
|
+
#if defined(_WIN32)
|
168
|
+
if ( RTEST(this->socket_io) )
|
169
|
+
rb_w32_unwrap_io_handle( this->ruby_sd );
|
170
|
+
#endif
|
169
171
|
if (this->pgconn != NULL)
|
170
172
|
PQfinish( this->pgconn );
|
171
173
|
|
@@ -198,7 +200,6 @@ pgconn_s_allocate( VALUE klass )
|
|
198
200
|
this->encoder_for_put_copy_data = Qnil;
|
199
201
|
this->decoder_for_get_copy_data = Qnil;
|
200
202
|
this->trace_stream = Qnil;
|
201
|
-
this->external_encoding = Qnil;
|
202
203
|
|
203
204
|
return self;
|
204
205
|
}
|
@@ -215,32 +216,27 @@ pgconn_s_allocate( VALUE klass )
|
|
215
216
|
*
|
216
217
|
* Create a connection to the specified server.
|
217
218
|
*
|
219
|
+
* +connection_hash+ must be a ruby Hash with connection parameters.
|
220
|
+
* See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
|
221
|
+
*
|
222
|
+
* There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
|
223
|
+
* See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
|
224
|
+
*
|
225
|
+
* The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
|
218
226
|
* [+host+]
|
219
227
|
* server hostname
|
220
|
-
* [+hostaddr+]
|
221
|
-
* server address (avoids hostname lookup, overrides +host+)
|
222
228
|
* [+port+]
|
223
229
|
* server port number
|
230
|
+
* [+options+]
|
231
|
+
* backend options
|
232
|
+
* [+tty+]
|
233
|
+
* (ignored in newer versions of PostgreSQL)
|
224
234
|
* [+dbname+]
|
225
235
|
* connecting database name
|
226
236
|
* [+user+]
|
227
237
|
* login user name
|
228
238
|
* [+password+]
|
229
239
|
* login password
|
230
|
-
* [+connect_timeout+]
|
231
|
-
* maximum time to wait for connection to succeed
|
232
|
-
* [+options+]
|
233
|
-
* backend options
|
234
|
-
* [+tty+]
|
235
|
-
* (ignored in newer versions of PostgreSQL)
|
236
|
-
* [+sslmode+]
|
237
|
-
* (disable|allow|prefer|require)
|
238
|
-
* [+krbsrvname+]
|
239
|
-
* kerberos service name
|
240
|
-
* [+gsslib+]
|
241
|
-
* GSS library to use for GSSAPI authentication
|
242
|
-
* [+service+]
|
243
|
-
* service name to use for additional parameters
|
244
240
|
*
|
245
241
|
* Examples:
|
246
242
|
*
|
@@ -256,7 +252,7 @@ pgconn_s_allocate( VALUE klass )
|
|
256
252
|
* # As an Array
|
257
253
|
* PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
|
258
254
|
*
|
259
|
-
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
255
|
+
* If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
|
260
256
|
* connection will have its +client_encoding+ set accordingly.
|
261
257
|
*
|
262
258
|
* Raises a PG::Error if the connection fails.
|
@@ -281,9 +277,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
281
277
|
rb_exc_raise(error);
|
282
278
|
}
|
283
279
|
|
284
|
-
#ifdef M17N_SUPPORTED
|
285
280
|
pgconn_set_default_encoding( self );
|
286
|
-
#endif
|
287
281
|
|
288
282
|
if (rb_block_given_p()) {
|
289
283
|
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
@@ -297,14 +291,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
297
291
|
* PG::Connection.connect_start(connection_string) -> conn
|
298
292
|
* PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
|
299
293
|
*
|
300
|
-
* This is an asynchronous version of PG::Connection.
|
294
|
+
* This is an asynchronous version of PG::Connection.new.
|
301
295
|
*
|
302
296
|
* Use #connect_poll to poll the status of the connection.
|
303
297
|
*
|
304
298
|
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
305
|
-
* Encoding.default_internal is set. To set it after the connection is established,
|
299
|
+
* +Encoding.default_internal+ is set. To set it after the connection is established,
|
306
300
|
* call #internal_encoding=. You can also set it automatically by setting
|
307
|
-
* ENV['PGCLIENTENCODING']
|
301
|
+
* <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
|
302
|
+
*
|
303
|
+
* See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
|
308
304
|
*
|
309
305
|
*/
|
310
306
|
static VALUE
|
@@ -339,15 +335,16 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
339
335
|
return rb_conn;
|
340
336
|
}
|
341
337
|
|
342
|
-
#ifdef HAVE_PQPING
|
343
338
|
/*
|
344
339
|
* call-seq:
|
345
|
-
* PG::Connection.ping(connection_hash) ->
|
346
|
-
* PG::Connection.ping(connection_string) ->
|
347
|
-
* PG::Connection.ping(host, port, options, tty, dbname, login, password) ->
|
340
|
+
* PG::Connection.ping(connection_hash) -> Integer
|
341
|
+
* PG::Connection.ping(connection_string) -> Integer
|
342
|
+
* PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
|
348
343
|
*
|
349
344
|
* Check server status.
|
350
345
|
*
|
346
|
+
* See PG::Connection.new for a description of the parameters.
|
347
|
+
*
|
351
348
|
* Returns one of:
|
352
349
|
* [+PQPING_OK+]
|
353
350
|
* server is accepting connections
|
@@ -369,11 +366,10 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
|
369
366
|
|
370
367
|
return INT2FIX((int)ping);
|
371
368
|
}
|
372
|
-
#endif
|
373
369
|
|
374
370
|
|
375
371
|
/*
|
376
|
-
* Document-method: conndefaults
|
372
|
+
* Document-method: PG::Connection.conndefaults
|
377
373
|
*
|
378
374
|
* call-seq:
|
379
375
|
* PG::Connection.conndefaults() -> Array
|
@@ -408,16 +404,62 @@ pgconn_s_conndefaults(VALUE self)
|
|
408
404
|
}
|
409
405
|
|
410
406
|
|
407
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
411
408
|
/*
|
412
409
|
* call-seq:
|
413
|
-
*
|
410
|
+
* conn.encrypt_password( password, username, algorithm=nil ) -> String
|
414
411
|
*
|
415
|
-
* This function is intended to be used by client applications that
|
416
|
-
* send
|
417
|
-
*
|
418
|
-
*
|
412
|
+
* This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
|
413
|
+
* It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on.
|
414
|
+
* Instead, use this function to convert the password to encrypted form before it is sent.
|
415
|
+
*
|
416
|
+
* The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
|
417
|
+
* +algorithm+ specifies the encryption algorithm to use to encrypt the password.
|
418
|
+
* Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions).
|
419
|
+
* Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
|
420
|
+
* If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
|
421
|
+
* That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
|
422
|
+
* If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm.
|
419
423
|
*
|
420
424
|
* Return value is the encrypted password.
|
425
|
+
* The caller can assume the string doesn't contain any special characters that would require escaping.
|
426
|
+
*
|
427
|
+
* Available since PostgreSQL-10.
|
428
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
|
429
|
+
*/
|
430
|
+
static VALUE
|
431
|
+
pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
|
432
|
+
{
|
433
|
+
char *encrypted = NULL;
|
434
|
+
VALUE rval = Qnil;
|
435
|
+
VALUE password, username, algorithm;
|
436
|
+
PGconn *conn = pg_get_pgconn(self);
|
437
|
+
|
438
|
+
rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
|
439
|
+
|
440
|
+
Check_Type(password, T_STRING);
|
441
|
+
Check_Type(username, T_STRING);
|
442
|
+
|
443
|
+
encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
444
|
+
if ( encrypted ) {
|
445
|
+
rval = rb_str_new2( encrypted );
|
446
|
+
PQfreemem( encrypted );
|
447
|
+
} else {
|
448
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
449
|
+
}
|
450
|
+
|
451
|
+
return rval;
|
452
|
+
}
|
453
|
+
#endif
|
454
|
+
|
455
|
+
|
456
|
+
/*
|
457
|
+
* call-seq:
|
458
|
+
* PG::Connection.encrypt_password( password, username ) -> String
|
459
|
+
*
|
460
|
+
* This is an older, deprecated version of #encrypt_password.
|
461
|
+
* The difference is that this function always uses +md5+ as the encryption algorithm.
|
462
|
+
*
|
421
463
|
*/
|
422
464
|
static VALUE
|
423
465
|
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
@@ -434,9 +476,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
434
476
|
rval = rb_str_new2( encrypted );
|
435
477
|
PQfreemem( encrypted );
|
436
478
|
|
437
|
-
OBJ_INFECT( rval, password );
|
438
|
-
OBJ_INFECT( rval, username );
|
439
|
-
|
440
479
|
return rval;
|
441
480
|
}
|
442
481
|
|
@@ -447,7 +486,7 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
447
486
|
|
448
487
|
/*
|
449
488
|
* call-seq:
|
450
|
-
* conn.connect_poll() ->
|
489
|
+
* conn.connect_poll() -> Integer
|
451
490
|
*
|
452
491
|
* Returns one of:
|
453
492
|
* [+PGRES_POLLING_READING+]
|
@@ -556,7 +595,7 @@ pgconn_reset_start(VALUE self)
|
|
556
595
|
|
557
596
|
/*
|
558
597
|
* call-seq:
|
559
|
-
* conn.reset_poll ->
|
598
|
+
* conn.reset_poll -> Integer
|
560
599
|
*
|
561
600
|
* Checks the status of a connection reset operation.
|
562
601
|
* See #connect_start and #connect_poll for
|
@@ -582,7 +621,7 @@ pgconn_db(VALUE self)
|
|
582
621
|
{
|
583
622
|
char *db = PQdb(pg_get_pgconn(self));
|
584
623
|
if (!db) return Qnil;
|
585
|
-
return
|
624
|
+
return rb_str_new2(db);
|
586
625
|
}
|
587
626
|
|
588
627
|
/*
|
@@ -596,21 +635,21 @@ pgconn_user(VALUE self)
|
|
596
635
|
{
|
597
636
|
char *user = PQuser(pg_get_pgconn(self));
|
598
637
|
if (!user) return Qnil;
|
599
|
-
return
|
638
|
+
return rb_str_new2(user);
|
600
639
|
}
|
601
640
|
|
602
641
|
/*
|
603
642
|
* call-seq:
|
604
643
|
* conn.pass()
|
605
644
|
*
|
606
|
-
* Returns the authenticated
|
645
|
+
* Returns the authenticated password.
|
607
646
|
*/
|
608
647
|
static VALUE
|
609
648
|
pgconn_pass(VALUE self)
|
610
649
|
{
|
611
650
|
char *user = PQpass(pg_get_pgconn(self));
|
612
651
|
if (!user) return Qnil;
|
613
|
-
return
|
652
|
+
return rb_str_new2(user);
|
614
653
|
}
|
615
654
|
|
616
655
|
/*
|
@@ -624,7 +663,7 @@ pgconn_host(VALUE self)
|
|
624
663
|
{
|
625
664
|
char *host = PQhost(pg_get_pgconn(self));
|
626
665
|
if (!host) return Qnil;
|
627
|
-
return
|
666
|
+
return rb_str_new2(host);
|
628
667
|
}
|
629
668
|
|
630
669
|
/*
|
@@ -651,7 +690,7 @@ pgconn_tty(VALUE self)
|
|
651
690
|
{
|
652
691
|
char *tty = PQtty(pg_get_pgconn(self));
|
653
692
|
if (!tty) return Qnil;
|
654
|
-
return
|
693
|
+
return rb_str_new2(tty);
|
655
694
|
}
|
656
695
|
|
657
696
|
/*
|
@@ -665,7 +704,7 @@ pgconn_options(VALUE self)
|
|
665
704
|
{
|
666
705
|
char *options = PQoptions(pg_get_pgconn(self));
|
667
706
|
if (!options) return Qnil;
|
668
|
-
return
|
707
|
+
return rb_str_new2(options);
|
669
708
|
}
|
670
709
|
|
671
710
|
|
@@ -676,6 +715,7 @@ pgconn_options(VALUE self)
|
|
676
715
|
*
|
677
716
|
* Returns the connection options used by a live connection.
|
678
717
|
*
|
718
|
+
* Available since PostgreSQL-9.3
|
679
719
|
*/
|
680
720
|
static VALUE
|
681
721
|
pgconn_conninfo( VALUE self )
|
@@ -745,7 +785,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
|
|
745
785
|
if(ret == NULL)
|
746
786
|
return Qnil;
|
747
787
|
else
|
748
|
-
return
|
788
|
+
return rb_str_new2(ret);
|
749
789
|
}
|
750
790
|
|
751
791
|
/*
|
@@ -790,12 +830,14 @@ pgconn_error_message(VALUE self)
|
|
790
830
|
{
|
791
831
|
char *error = PQerrorMessage(pg_get_pgconn(self));
|
792
832
|
if (!error) return Qnil;
|
793
|
-
return
|
833
|
+
return rb_str_new2(error);
|
794
834
|
}
|
795
835
|
|
796
836
|
/*
|
797
837
|
* call-seq:
|
798
|
-
* conn.socket() ->
|
838
|
+
* conn.socket() -> Integer
|
839
|
+
*
|
840
|
+
* This method is deprecated. Please use the more portable method #socket_io .
|
799
841
|
*
|
800
842
|
* Returns the socket's file descriptor for this connection.
|
801
843
|
* <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
|
@@ -805,34 +847,31 @@ pgconn_error_message(VALUE self)
|
|
805
847
|
* creates an IO that's associated with the connection object itself,
|
806
848
|
* and so won't go out of scope until the connection does.
|
807
849
|
*
|
808
|
-
* *Note:* On Windows the file descriptor is not
|
850
|
+
* *Note:* On Windows the file descriptor is not usable,
|
809
851
|
* since it can not be used to build a Ruby IO object.
|
810
852
|
*/
|
811
853
|
static VALUE
|
812
854
|
pgconn_socket(VALUE self)
|
813
855
|
{
|
814
856
|
int sd;
|
857
|
+
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
858
|
+
|
815
859
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
816
860
|
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
817
861
|
return INT2NUM(sd);
|
818
862
|
}
|
819
863
|
|
820
|
-
|
821
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
822
|
-
|
823
864
|
/*
|
824
865
|
* call-seq:
|
825
866
|
* conn.socket_io() -> IO
|
826
867
|
*
|
827
|
-
* Fetch a
|
868
|
+
* Fetch a memorized IO object created from the Connection's underlying socket.
|
828
869
|
* This object can be used for IO.select to wait for events while running
|
829
870
|
* asynchronous API calls.
|
830
871
|
*
|
831
872
|
* Using this instead of #socket avoids the problem of the underlying connection
|
832
873
|
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
833
|
-
* goes out of scope.
|
834
|
-
*
|
835
|
-
* This method can also be used on Windows but requires Ruby-2.0+.
|
874
|
+
* goes out of scope. In contrast to #socket, it also works on Windows.
|
836
875
|
*/
|
837
876
|
static VALUE
|
838
877
|
pgconn_socket_io(VALUE self)
|
@@ -849,16 +888,15 @@ pgconn_socket_io(VALUE self)
|
|
849
888
|
|
850
889
|
#ifdef _WIN32
|
851
890
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
891
|
+
this->ruby_sd = ruby_sd;
|
852
892
|
#else
|
853
893
|
ruby_sd = sd;
|
854
894
|
#endif
|
855
895
|
|
856
896
|
socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
|
857
897
|
|
858
|
-
/* Disable autoclose feature
|
859
|
-
|
860
|
-
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
861
|
-
}
|
898
|
+
/* Disable autoclose feature */
|
899
|
+
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
862
900
|
|
863
901
|
this->socket_io = socket_io;
|
864
902
|
}
|
@@ -866,11 +904,9 @@ pgconn_socket_io(VALUE self)
|
|
866
904
|
return socket_io;
|
867
905
|
}
|
868
906
|
|
869
|
-
#endif
|
870
|
-
|
871
907
|
/*
|
872
908
|
* call-seq:
|
873
|
-
* conn.backend_pid() ->
|
909
|
+
* conn.backend_pid() -> Integer
|
874
910
|
*
|
875
911
|
* Returns the process ID of the backend server
|
876
912
|
* process for this connection.
|
@@ -916,40 +952,31 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
916
952
|
|
917
953
|
/*
|
918
954
|
* call-seq:
|
919
|
-
* conn.
|
920
|
-
* conn.
|
921
|
-
*
|
922
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
923
|
-
* Returns a PG::Result instance on success.
|
924
|
-
* On failure, it raises a PG::Error.
|
955
|
+
* conn.sync_exec(sql) -> PG::Result
|
956
|
+
* conn.sync_exec(sql) {|pg_result| block }
|
925
957
|
*
|
926
|
-
*
|
927
|
-
*
|
928
|
-
* argument placeholders are used.
|
958
|
+
* This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
|
959
|
+
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
929
960
|
*
|
930
|
-
*
|
931
|
-
*
|
932
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
961
|
+
* Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
|
962
|
+
* However #async_exec has two advantages:
|
933
963
|
*
|
934
|
-
* #
|
935
|
-
*
|
936
|
-
*
|
937
|
-
* the query is finished. This is most notably visible by a delayed reaction to Control+C.
|
938
|
-
* Both methods ensure that other threads can process while waiting for the server to
|
939
|
-
* complete the request.
|
964
|
+
* 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
965
|
+
* 2. Ruby VM gets notified about IO blocked operations.
|
966
|
+
* It can therefore schedule things like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
|
940
967
|
*/
|
941
968
|
static VALUE
|
942
969
|
pgconn_exec(int argc, VALUE *argv, VALUE self)
|
943
970
|
{
|
944
|
-
|
971
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
945
972
|
PGresult *result = NULL;
|
946
973
|
VALUE rb_pgresult;
|
947
974
|
|
948
|
-
/* If called with no parameters, use PQexec */
|
949
|
-
if ( argc == 1 ) {
|
950
|
-
|
975
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
976
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
977
|
+
VALUE query_str = argv[0];
|
951
978
|
|
952
|
-
result = gvl_PQexec(
|
979
|
+
result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
|
953
980
|
rb_pgresult = pg_new_result(result, self);
|
954
981
|
pg_result_check(rb_pgresult);
|
955
982
|
if (rb_block_given_p()) {
|
@@ -957,11 +984,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
957
984
|
}
|
958
985
|
return rb_pgresult;
|
959
986
|
}
|
987
|
+
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
960
988
|
|
961
989
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
962
|
-
|
963
|
-
return pgconn_exec_params( argc, argv, self );
|
964
|
-
}
|
990
|
+
return pgconn_exec_params( argc, argv, self );
|
965
991
|
|
966
992
|
}
|
967
993
|
|
@@ -978,6 +1004,10 @@ struct query_params_data {
|
|
978
1004
|
* Filled by caller
|
979
1005
|
*/
|
980
1006
|
|
1007
|
+
/* The character encoding index of the connection. Any strings
|
1008
|
+
* given as query parameters are converted to this encoding.
|
1009
|
+
*/
|
1010
|
+
int enc_idx;
|
981
1011
|
/* Is the query function to execute one with types array? */
|
982
1012
|
int with_types;
|
983
1013
|
/* Array of query params from user space */
|
@@ -1138,7 +1168,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1138
1168
|
VALUE intermediate;
|
1139
1169
|
|
1140
1170
|
/* 1st pass for retiving the required memory space */
|
1141
|
-
int len = enc_func(conv, param_value, NULL, &intermediate);
|
1171
|
+
int len = enc_func(conv, param_value, NULL, &intermediate, paramsData->enc_idx);
|
1142
1172
|
|
1143
1173
|
if( len == -1 ){
|
1144
1174
|
/* The intermediate value is a String that can be used directly. */
|
@@ -1162,7 +1192,7 @@ alloc_query_params(struct query_params_data *paramsData)
|
|
1162
1192
|
}
|
1163
1193
|
|
1164
1194
|
/* 2nd pass for writing the data to prepared buffer */
|
1165
|
-
len = enc_func(conv, param_value, typecast_buf, &intermediate);
|
1195
|
+
len = enc_func(conv, param_value, typecast_buf, &intermediate, paramsData->enc_idx);
|
1166
1196
|
paramsData->values[i] = typecast_buf;
|
1167
1197
|
if( paramsData->formats[i] == 0 ){
|
1168
1198
|
/* text format strings must be zero terminated and lengths are ignored */
|
@@ -1208,66 +1238,34 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1208
1238
|
|
1209
1239
|
/*
|
1210
1240
|
* call-seq:
|
1211
|
-
* conn.
|
1212
|
-
* conn.
|
1213
|
-
*
|
1214
|
-
* Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
|
1215
|
-
* for parameters.
|
1216
|
-
*
|
1217
|
-
* Returns a PG::Result instance on success. On failure, it raises a PG::Error.
|
1218
|
-
*
|
1219
|
-
* +params+ is an array of the bind parameters for the SQL query.
|
1220
|
-
* Each element of the +params+ array may be either:
|
1221
|
-
* a hash of the form:
|
1222
|
-
* {:value => String (value of bind parameter)
|
1223
|
-
* :type => Fixnum (oid of type of bind parameter)
|
1224
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1225
|
-
* }
|
1226
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1227
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
1228
|
-
*
|
1229
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1230
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1231
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1232
|
-
*
|
1233
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1234
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1235
|
-
* explicit casts in the query to ensure that the right type is used.
|
1236
|
-
*
|
1237
|
-
* For example: "SELECT $1::int"
|
1241
|
+
* conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
|
1242
|
+
* conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
|
1238
1243
|
*
|
1239
|
-
*
|
1240
|
-
* for
|
1241
|
-
*
|
1242
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1243
|
-
* This will type cast the params form various Ruby types before transmission
|
1244
|
-
* based on the encoders defined by the type map. When a type encoder is used
|
1245
|
-
* the format and oid of a given bind parameter are retrieved from the encoder
|
1246
|
-
* instead out of the hash form described above.
|
1247
|
-
*
|
1248
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1249
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
1250
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
1244
|
+
* This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
|
1245
|
+
* See #async_exec for the differences between the two API variants.
|
1246
|
+
* It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
|
1251
1247
|
*/
|
1252
1248
|
static VALUE
|
1253
1249
|
pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
1254
1250
|
{
|
1255
|
-
|
1251
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1256
1252
|
PGresult *result = NULL;
|
1257
1253
|
VALUE rb_pgresult;
|
1258
1254
|
VALUE command, in_res_fmt;
|
1259
1255
|
int nParams;
|
1260
1256
|
int resultFormat;
|
1261
|
-
struct query_params_data paramsData;
|
1257
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1262
1258
|
|
1259
|
+
/* For compatibility we accept 1 to 4 parameters */
|
1263
1260
|
rb_scan_args(argc, argv, "13", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1264
1261
|
paramsData.with_types = 1;
|
1265
1262
|
|
1266
1263
|
/*
|
1267
|
-
*
|
1268
|
-
*
|
1264
|
+
* For backward compatibility no or +nil+ for the second parameter
|
1265
|
+
* is passed to #exec
|
1269
1266
|
*/
|
1270
1267
|
if ( NIL_P(paramsData.params) ) {
|
1268
|
+
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1271
1269
|
return pgconn_exec( 1, argv, self );
|
1272
1270
|
}
|
1273
1271
|
pgconn_query_assign_typemap( self, ¶msData );
|
@@ -1275,7 +1273,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1275
1273
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1276
1274
|
nParams = alloc_query_params( ¶msData );
|
1277
1275
|
|
1278
|
-
result = gvl_PQexecParams(
|
1276
|
+
result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1279
1277
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1280
1278
|
|
1281
1279
|
free_query_params( ¶msData );
|
@@ -1292,28 +1290,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1292
1290
|
|
1293
1291
|
/*
|
1294
1292
|
* call-seq:
|
1295
|
-
* conn.
|
1296
|
-
*
|
1297
|
-
* Prepares statement _sql_ with name _name_ to be executed later.
|
1298
|
-
* Returns a PG::Result instance on success.
|
1299
|
-
* On failure, it raises a PG::Error.
|
1300
|
-
*
|
1301
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1302
|
-
* types of the parameters.
|
1303
|
-
*
|
1304
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1305
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1306
|
-
* explicit casts in the query to ensure that the right type is used.
|
1293
|
+
* conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
1307
1294
|
*
|
1308
|
-
*
|
1309
|
-
*
|
1310
|
-
*
|
1311
|
-
* inside the SQL query.
|
1295
|
+
* This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
|
1296
|
+
* See #async_exec for the differences between the two API variants.
|
1297
|
+
* It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
|
1312
1298
|
*/
|
1313
1299
|
static VALUE
|
1314
1300
|
pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
1315
1301
|
{
|
1316
|
-
|
1302
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1317
1303
|
PGresult *result = NULL;
|
1318
1304
|
VALUE rb_pgresult;
|
1319
1305
|
VALUE name, command, in_paramtypes;
|
@@ -1321,10 +1307,13 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1321
1307
|
int i = 0;
|
1322
1308
|
int nParams = 0;
|
1323
1309
|
Oid *paramTypes = NULL;
|
1310
|
+
const char *name_cstr;
|
1311
|
+
const char *command_cstr;
|
1312
|
+
int enc_idx = this->enc_idx;
|
1324
1313
|
|
1325
1314
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1326
|
-
|
1327
|
-
|
1315
|
+
name_cstr = pg_cstr_enc(name, enc_idx);
|
1316
|
+
command_cstr = pg_cstr_enc(command, enc_idx);
|
1328
1317
|
|
1329
1318
|
if(! NIL_P(in_paramtypes)) {
|
1330
1319
|
Check_Type(in_paramtypes, T_ARRAY);
|
@@ -1338,8 +1327,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1338
1327
|
paramTypes[i] = NUM2UINT(param);
|
1339
1328
|
}
|
1340
1329
|
}
|
1341
|
-
result = gvl_PQprepare(
|
1342
|
-
nParams, paramTypes);
|
1330
|
+
result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
1343
1331
|
|
1344
1332
|
xfree(paramTypes);
|
1345
1333
|
|
@@ -1350,53 +1338,26 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1350
1338
|
|
1351
1339
|
/*
|
1352
1340
|
* call-seq:
|
1353
|
-
* conn.
|
1354
|
-
* conn.
|
1355
|
-
*
|
1356
|
-
* Execute prepared named statement specified by _statement_name_.
|
1357
|
-
* Returns a PG::Result instance on success.
|
1358
|
-
* On failure, it raises a PG::Error.
|
1359
|
-
*
|
1360
|
-
* +params+ is an array of the optional bind parameters for the
|
1361
|
-
* SQL query. Each element of the +params+ array may be either:
|
1362
|
-
* a hash of the form:
|
1363
|
-
* {:value => String (value of bind parameter)
|
1364
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1365
|
-
* }
|
1366
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1367
|
-
* { :value => <string value>, :format => 0 }
|
1368
|
-
*
|
1369
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1370
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1371
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1341
|
+
* conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
1342
|
+
* conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
1372
1343
|
*
|
1373
|
-
*
|
1374
|
-
* for
|
1375
|
-
*
|
1376
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1377
|
-
* This will type cast the params form various Ruby types before transmission
|
1378
|
-
* based on the encoders defined by the type map. When a type encoder is used
|
1379
|
-
* the format and oid of a given bind parameter are retrieved from the encoder
|
1380
|
-
* instead out of the hash form described above.
|
1381
|
-
*
|
1382
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1383
|
-
* and the PG::Result object will automatically be cleared when the block terminates.
|
1384
|
-
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
1344
|
+
* This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
|
1345
|
+
* See #async_exec for the differences between the two API variants.
|
1346
|
+
* It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
|
1385
1347
|
*/
|
1386
1348
|
static VALUE
|
1387
1349
|
pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1388
1350
|
{
|
1389
|
-
|
1351
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1390
1352
|
PGresult *result = NULL;
|
1391
1353
|
VALUE rb_pgresult;
|
1392
1354
|
VALUE name, in_res_fmt;
|
1393
1355
|
int nParams;
|
1394
1356
|
int resultFormat;
|
1395
|
-
struct query_params_data paramsData;
|
1357
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1396
1358
|
|
1397
1359
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1398
1360
|
paramsData.with_types = 0;
|
1399
|
-
Check_Type(name, T_STRING);
|
1400
1361
|
|
1401
1362
|
if(NIL_P(paramsData.params)) {
|
1402
1363
|
paramsData.params = rb_ary_new2(0);
|
@@ -1406,7 +1367,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1406
1367
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1407
1368
|
nParams = alloc_query_params( ¶msData );
|
1408
1369
|
|
1409
|
-
result = gvl_PQexecPrepared(
|
1370
|
+
result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1410
1371
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1411
1372
|
resultFormat);
|
1412
1373
|
|
@@ -1423,26 +1384,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
|
1423
1384
|
|
1424
1385
|
/*
|
1425
1386
|
* call-seq:
|
1426
|
-
* conn.
|
1387
|
+
* conn.sync_describe_prepared( statement_name ) -> PG::Result
|
1427
1388
|
*
|
1428
|
-
*
|
1429
|
-
*
|
1389
|
+
* This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
|
1390
|
+
* See #async_exec for the differences between the two API variants.
|
1391
|
+
* It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
|
1430
1392
|
*/
|
1431
1393
|
static VALUE
|
1432
1394
|
pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
1433
1395
|
{
|
1434
1396
|
PGresult *result;
|
1435
1397
|
VALUE rb_pgresult;
|
1436
|
-
|
1437
|
-
char *stmt;
|
1438
|
-
if(stmt_name
|
1398
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1399
|
+
const char *stmt;
|
1400
|
+
if(NIL_P(stmt_name)) {
|
1439
1401
|
stmt = NULL;
|
1440
1402
|
}
|
1441
1403
|
else {
|
1442
|
-
|
1443
|
-
stmt = StringValueCStr(stmt_name);
|
1404
|
+
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1444
1405
|
}
|
1445
|
-
result = gvl_PQdescribePrepared(
|
1406
|
+
result = gvl_PQdescribePrepared(this->pgconn, stmt);
|
1446
1407
|
rb_pgresult = pg_new_result(result, self);
|
1447
1408
|
pg_result_check(rb_pgresult);
|
1448
1409
|
return rb_pgresult;
|
@@ -1451,9 +1412,11 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1451
1412
|
|
1452
1413
|
/*
|
1453
1414
|
* call-seq:
|
1454
|
-
* conn.
|
1415
|
+
* conn.sync_describe_portal( portal_name ) -> PG::Result
|
1455
1416
|
*
|
1456
|
-
*
|
1417
|
+
* This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
|
1418
|
+
* See #async_exec for the differences between the two API variants.
|
1419
|
+
* It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
|
1457
1420
|
*/
|
1458
1421
|
static VALUE
|
1459
1422
|
pgconn_describe_portal(self, stmt_name)
|
@@ -1461,16 +1424,15 @@ pgconn_describe_portal(self, stmt_name)
|
|
1461
1424
|
{
|
1462
1425
|
PGresult *result;
|
1463
1426
|
VALUE rb_pgresult;
|
1464
|
-
|
1465
|
-
char *stmt;
|
1466
|
-
if(stmt_name
|
1427
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1428
|
+
const char *stmt;
|
1429
|
+
if(NIL_P(stmt_name)) {
|
1467
1430
|
stmt = NULL;
|
1468
1431
|
}
|
1469
1432
|
else {
|
1470
|
-
|
1471
|
-
stmt = StringValueCStr(stmt_name);
|
1433
|
+
stmt = pg_cstr_enc(stmt_name, this->enc_idx);
|
1472
1434
|
}
|
1473
|
-
result = gvl_PQdescribePortal(
|
1435
|
+
result = gvl_PQdescribePortal(this->pgconn, stmt);
|
1474
1436
|
rb_pgresult = pg_new_result(result, self);
|
1475
1437
|
pg_result_check(rb_pgresult);
|
1476
1438
|
return rb_pgresult;
|
@@ -1510,10 +1472,6 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1510
1472
|
* call-seq:
|
1511
1473
|
* conn.escape_string( str ) -> String
|
1512
1474
|
*
|
1513
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1514
|
-
* uses PQescapeStringConn, which is safer. Avoid calling as a class method,
|
1515
|
-
* the class method uses the deprecated PQescapeString() API function.
|
1516
|
-
*
|
1517
1475
|
* Returns a SQL-safe version of the String _str_.
|
1518
1476
|
* This is the preferred way to make strings safe for inclusion in
|
1519
1477
|
* SQL queries.
|
@@ -1521,33 +1479,43 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
|
1521
1479
|
* Consider using exec_params, which avoids the need for passing values
|
1522
1480
|
* inside of SQL commands.
|
1523
1481
|
*
|
1524
|
-
*
|
1482
|
+
* Character encoding of escaped string will be equal to client encoding of connection.
|
1483
|
+
*
|
1484
|
+
* NOTE: This class version of this method can only be used safely in client
|
1485
|
+
* programs that use a single PostgreSQL connection at a time (in this case it can
|
1486
|
+
* find out what it needs to know "behind the scenes"). It might give the wrong
|
1487
|
+
* results if used in programs that use multiple database connections; use the
|
1488
|
+
* same method on the connection object in such cases.
|
1489
|
+
*
|
1490
|
+
* See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
|
1525
1491
|
*/
|
1526
1492
|
static VALUE
|
1527
1493
|
pgconn_s_escape(VALUE self, VALUE string)
|
1528
1494
|
{
|
1529
|
-
char *escaped;
|
1530
1495
|
size_t size;
|
1531
1496
|
int error;
|
1532
1497
|
VALUE result;
|
1498
|
+
int enc_idx;
|
1499
|
+
int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
|
1533
1500
|
|
1534
|
-
|
1501
|
+
StringValueCStr(string);
|
1502
|
+
enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
|
1503
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1504
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1505
|
+
}
|
1535
1506
|
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1507
|
+
result = rb_str_new(NULL, RSTRING_LEN(string) * 2 + 1);
|
1508
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1509
|
+
if( !singleton ) {
|
1510
|
+
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
1539
1511
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1540
1512
|
if(error) {
|
1541
|
-
xfree(escaped);
|
1542
1513
|
rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
1543
1514
|
}
|
1544
1515
|
} else {
|
1545
|
-
size = PQescapeString(
|
1516
|
+
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1546
1517
|
}
|
1547
|
-
result
|
1548
|
-
xfree(escaped);
|
1549
|
-
OBJ_INFECT(result, string);
|
1550
|
-
PG_ENCODING_SET_NOCHECK(result, ENCODING_GET( rb_obj_is_kind_of(self, rb_cPGconn) ? self : string ));
|
1518
|
+
rb_str_set_len(result, size);
|
1551
1519
|
|
1552
1520
|
return result;
|
1553
1521
|
}
|
@@ -1556,13 +1524,6 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1556
1524
|
* call-seq:
|
1557
1525
|
* conn.escape_bytea( string ) -> String
|
1558
1526
|
*
|
1559
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1560
|
-
* uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
|
1561
|
-
* the class method uses the deprecated PQescapeBytea() API function.
|
1562
|
-
*
|
1563
|
-
* Use the instance method version of this function, it is safer than the
|
1564
|
-
* class method.
|
1565
|
-
*
|
1566
1527
|
* Escapes binary data for use within an SQL command with the type +bytea+.
|
1567
1528
|
*
|
1568
1529
|
* Certain byte values must be escaped (but all byte values may be escaped)
|
@@ -1575,6 +1536,12 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1575
1536
|
*
|
1576
1537
|
* Consider using exec_params, which avoids the need for passing values inside of
|
1577
1538
|
* SQL commands.
|
1539
|
+
*
|
1540
|
+
* NOTE: This class version of this method can only be used safely in client
|
1541
|
+
* programs that use a single PostgreSQL connection at a time (in this case it can
|
1542
|
+
* find out what it needs to know "behind the scenes"). It might give the wrong
|
1543
|
+
* results if used in programs that use multiple database connections; use the
|
1544
|
+
* same method on the connection object in such cases.
|
1578
1545
|
*/
|
1579
1546
|
static VALUE
|
1580
1547
|
pgconn_s_escape_bytea(VALUE self, VALUE str)
|
@@ -1594,7 +1561,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
|
|
1594
1561
|
}
|
1595
1562
|
|
1596
1563
|
ret = rb_str_new((char*)to, to_len - 1);
|
1597
|
-
OBJ_INFECT(ret, str);
|
1598
1564
|
PQfreemem(to);
|
1599
1565
|
return ret;
|
1600
1566
|
}
|
@@ -1624,83 +1590,86 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
|
1624
1590
|
to = PQunescapeBytea(from, &to_len);
|
1625
1591
|
|
1626
1592
|
ret = rb_str_new((char*)to, to_len);
|
1627
|
-
OBJ_INFECT(ret, str);
|
1628
1593
|
PQfreemem(to);
|
1629
1594
|
return ret;
|
1630
1595
|
}
|
1631
1596
|
|
1632
|
-
#ifdef HAVE_PQESCAPELITERAL
|
1633
1597
|
/*
|
1634
1598
|
* call-seq:
|
1635
1599
|
* conn.escape_literal( str ) -> String
|
1636
1600
|
*
|
1637
1601
|
* Escape an arbitrary String +str+ as a literal.
|
1602
|
+
*
|
1603
|
+
* See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
|
1638
1604
|
*/
|
1639
1605
|
static VALUE
|
1640
1606
|
pgconn_escape_literal(VALUE self, VALUE string)
|
1641
1607
|
{
|
1642
|
-
|
1608
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1643
1609
|
char *escaped = NULL;
|
1644
1610
|
VALUE error;
|
1645
1611
|
VALUE result = Qnil;
|
1612
|
+
int enc_idx = this->enc_idx;
|
1646
1613
|
|
1647
|
-
|
1614
|
+
StringValueCStr(string);
|
1615
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1616
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1617
|
+
}
|
1648
1618
|
|
1649
|
-
escaped = PQescapeLiteral(
|
1619
|
+
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1650
1620
|
if (escaped == NULL)
|
1651
1621
|
{
|
1652
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
1622
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
1653
1623
|
rb_iv_set(error, "@connection", self);
|
1654
1624
|
rb_exc_raise(error);
|
1655
1625
|
return Qnil;
|
1656
1626
|
}
|
1657
1627
|
result = rb_str_new2(escaped);
|
1658
1628
|
PQfreemem(escaped);
|
1659
|
-
|
1660
|
-
PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
|
1629
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1661
1630
|
|
1662
1631
|
return result;
|
1663
1632
|
}
|
1664
|
-
#endif
|
1665
1633
|
|
1666
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
1667
1634
|
/*
|
1668
1635
|
* call-seq:
|
1669
1636
|
* conn.escape_identifier( str ) -> String
|
1670
1637
|
*
|
1671
1638
|
* Escape an arbitrary String +str+ as an identifier.
|
1672
1639
|
*
|
1673
|
-
* This method does the same as #quote_ident
|
1674
|
-
*
|
1640
|
+
* This method does the same as #quote_ident with a String argument,
|
1641
|
+
* but it doesn't support an Array argument and it makes use of libpq
|
1642
|
+
* to process the string.
|
1675
1643
|
*/
|
1676
1644
|
static VALUE
|
1677
1645
|
pgconn_escape_identifier(VALUE self, VALUE string)
|
1678
1646
|
{
|
1679
|
-
|
1647
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1680
1648
|
char *escaped = NULL;
|
1681
1649
|
VALUE error;
|
1682
1650
|
VALUE result = Qnil;
|
1651
|
+
int enc_idx = this->enc_idx;
|
1683
1652
|
|
1684
|
-
|
1653
|
+
StringValueCStr(string);
|
1654
|
+
if( ENCODING_GET(string) != enc_idx ){
|
1655
|
+
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1656
|
+
}
|
1685
1657
|
|
1686
|
-
escaped = PQescapeIdentifier(
|
1658
|
+
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1687
1659
|
if (escaped == NULL)
|
1688
1660
|
{
|
1689
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
1661
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
1690
1662
|
rb_iv_set(error, "@connection", self);
|
1691
1663
|
rb_exc_raise(error);
|
1692
1664
|
return Qnil;
|
1693
1665
|
}
|
1694
1666
|
result = rb_str_new2(escaped);
|
1695
1667
|
PQfreemem(escaped);
|
1696
|
-
|
1697
|
-
PG_ENCODING_SET_NOCHECK(result, ENCODING_GET(self));
|
1668
|
+
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
1698
1669
|
|
1699
1670
|
return result;
|
1700
1671
|
}
|
1701
|
-
#endif
|
1702
1672
|
|
1703
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1704
1673
|
/*
|
1705
1674
|
* call-seq:
|
1706
1675
|
* conn.set_single_row_mode -> self
|
@@ -1736,7 +1705,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1736
1705
|
* # do something with the received row
|
1737
1706
|
* end
|
1738
1707
|
* end
|
1739
|
-
*
|
1740
1708
|
*/
|
1741
1709
|
static VALUE
|
1742
1710
|
pgconn_set_single_row_mode(VALUE self)
|
@@ -1753,22 +1721,60 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1753
1721
|
|
1754
1722
|
return self;
|
1755
1723
|
}
|
1756
|
-
|
1724
|
+
|
1725
|
+
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1726
|
+
|
1727
|
+
/*
|
1728
|
+
* call-seq:
|
1729
|
+
* conn.send_query(sql) -> nil
|
1730
|
+
*
|
1731
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1732
|
+
* asynchronous processing, and immediately returns.
|
1733
|
+
* On failure, it raises a PG::Error.
|
1734
|
+
*
|
1735
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
1736
|
+
* it will call #send_query_params for you. New code should explicitly use #send_query_params if
|
1737
|
+
* argument placeholders are used.
|
1738
|
+
*
|
1739
|
+
*/
|
1740
|
+
static VALUE
|
1741
|
+
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1742
|
+
{
|
1743
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1744
|
+
VALUE error;
|
1745
|
+
|
1746
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
1747
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1748
|
+
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
|
1749
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1750
|
+
rb_iv_set(error, "@connection", self);
|
1751
|
+
rb_exc_raise(error);
|
1752
|
+
}
|
1753
|
+
return Qnil;
|
1754
|
+
}
|
1755
|
+
|
1756
|
+
pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
|
1757
|
+
|
1758
|
+
/* If called with parameters, and optionally result_format,
|
1759
|
+
* use PQsendQueryParams
|
1760
|
+
*/
|
1761
|
+
return pgconn_send_query_params( argc, argv, self);
|
1762
|
+
}
|
1757
1763
|
|
1758
1764
|
/*
|
1759
1765
|
* call-seq:
|
1760
|
-
* conn.
|
1766
|
+
* conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
|
1761
1767
|
*
|
1762
1768
|
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1763
1769
|
* asynchronous processing, and immediately returns.
|
1764
1770
|
* On failure, it raises a PG::Error.
|
1765
1771
|
*
|
1766
|
-
* +params+ is an
|
1772
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
1767
1773
|
* Each element of the +params+ array may be either:
|
1768
1774
|
* a hash of the form:
|
1769
1775
|
* {:value => String (value of bind parameter)
|
1770
|
-
* :type =>
|
1771
|
-
* :format =>
|
1776
|
+
* :type => Integer (oid of type of bind parameter)
|
1777
|
+
* :format => Integer (0 for text, 1 for binary)
|
1772
1778
|
* }
|
1773
1779
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1774
1780
|
* { :value => <string value>, :type => 0, :format => 0 }
|
@@ -1786,53 +1792,38 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1786
1792
|
* The optional +result_format+ should be 0 for text results, 1
|
1787
1793
|
* for binary.
|
1788
1794
|
*
|
1789
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1790
|
-
* This will type cast the params
|
1795
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1796
|
+
* This will type cast the params from various Ruby types before transmission
|
1791
1797
|
* based on the encoders defined by the type map. When a type encoder is used
|
1792
1798
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1793
1799
|
* instead out of the hash form described above.
|
1794
1800
|
*
|
1795
1801
|
*/
|
1796
1802
|
static VALUE
|
1797
|
-
|
1803
|
+
pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
1798
1804
|
{
|
1799
|
-
|
1805
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1800
1806
|
int result;
|
1801
1807
|
VALUE command, in_res_fmt;
|
1802
1808
|
VALUE error;
|
1803
1809
|
int nParams;
|
1804
1810
|
int resultFormat;
|
1805
|
-
struct query_params_data paramsData;
|
1811
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1806
1812
|
|
1807
|
-
rb_scan_args(argc, argv, "
|
1813
|
+
rb_scan_args(argc, argv, "22", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1808
1814
|
paramsData.with_types = 1;
|
1809
|
-
Check_Type(command, T_STRING);
|
1810
|
-
|
1811
|
-
/* If called with no parameters, use PQsendQuery */
|
1812
|
-
if(NIL_P(paramsData.params)) {
|
1813
|
-
if(gvl_PQsendQuery(conn,StringValueCStr(command)) == 0) {
|
1814
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1815
|
-
rb_iv_set(error, "@connection", self);
|
1816
|
-
rb_exc_raise(error);
|
1817
|
-
}
|
1818
|
-
return Qnil;
|
1819
|
-
}
|
1820
|
-
|
1821
|
-
/* If called with parameters, and optionally result_format,
|
1822
|
-
* use PQsendQueryParams
|
1823
|
-
*/
|
1824
1815
|
|
1825
1816
|
pgconn_query_assign_typemap( self, ¶msData );
|
1826
1817
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1827
1818
|
nParams = alloc_query_params( ¶msData );
|
1828
1819
|
|
1829
|
-
result = gvl_PQsendQueryParams(
|
1820
|
+
result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
|
1830
1821
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
|
1831
1822
|
|
1832
1823
|
free_query_params( ¶msData );
|
1833
1824
|
|
1834
1825
|
if(result == 0) {
|
1835
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1826
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1836
1827
|
rb_iv_set(error, "@connection", self);
|
1837
1828
|
rb_exc_raise(error);
|
1838
1829
|
}
|
@@ -1862,7 +1853,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1862
1853
|
static VALUE
|
1863
1854
|
pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
1864
1855
|
{
|
1865
|
-
|
1856
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1866
1857
|
int result;
|
1867
1858
|
VALUE name, command, in_paramtypes;
|
1868
1859
|
VALUE param;
|
@@ -1870,10 +1861,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1870
1861
|
int i = 0;
|
1871
1862
|
int nParams = 0;
|
1872
1863
|
Oid *paramTypes = NULL;
|
1864
|
+
const char *name_cstr;
|
1865
|
+
const char *command_cstr;
|
1866
|
+
int enc_idx = this->enc_idx;
|
1873
1867
|
|
1874
1868
|
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1875
|
-
|
1876
|
-
|
1869
|
+
name_cstr = pg_cstr_enc(name, enc_idx);
|
1870
|
+
command_cstr = pg_cstr_enc(command, enc_idx);
|
1877
1871
|
|
1878
1872
|
if(! NIL_P(in_paramtypes)) {
|
1879
1873
|
Check_Type(in_paramtypes, T_ARRAY);
|
@@ -1887,13 +1881,12 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1887
1881
|
paramTypes[i] = NUM2UINT(param);
|
1888
1882
|
}
|
1889
1883
|
}
|
1890
|
-
result = gvl_PQsendPrepare(
|
1891
|
-
nParams, paramTypes);
|
1884
|
+
result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
|
1892
1885
|
|
1893
1886
|
xfree(paramTypes);
|
1894
1887
|
|
1895
1888
|
if(result == 0) {
|
1896
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1889
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1897
1890
|
rb_iv_set(error, "@connection", self);
|
1898
1891
|
rb_exc_raise(error);
|
1899
1892
|
}
|
@@ -1913,7 +1906,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1913
1906
|
* SQL query. Each element of the +params+ array may be either:
|
1914
1907
|
* a hash of the form:
|
1915
1908
|
* {:value => String (value of bind parameter)
|
1916
|
-
* :format =>
|
1909
|
+
* :format => Integer (0 for text, 1 for binary)
|
1917
1910
|
* }
|
1918
1911
|
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1919
1912
|
* { :value => <string value>, :format => 0 }
|
@@ -1925,8 +1918,8 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1925
1918
|
* The optional +result_format+ should be 0 for text results, 1
|
1926
1919
|
* for binary.
|
1927
1920
|
*
|
1928
|
-
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1929
|
-
* This will type cast the params
|
1921
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1922
|
+
* This will type cast the params from various Ruby types before transmission
|
1930
1923
|
* based on the encoders defined by the type map. When a type encoder is used
|
1931
1924
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1932
1925
|
* instead out of the hash form described above.
|
@@ -1935,17 +1928,16 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1935
1928
|
static VALUE
|
1936
1929
|
pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
1937
1930
|
{
|
1938
|
-
|
1931
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1939
1932
|
int result;
|
1940
1933
|
VALUE name, in_res_fmt;
|
1941
1934
|
VALUE error;
|
1942
1935
|
int nParams;
|
1943
1936
|
int resultFormat;
|
1944
|
-
struct query_params_data paramsData;
|
1937
|
+
struct query_params_data paramsData = { this->enc_idx };
|
1945
1938
|
|
1946
1939
|
rb_scan_args(argc, argv, "13", &name, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1947
1940
|
paramsData.with_types = 0;
|
1948
|
-
Check_Type(name, T_STRING);
|
1949
1941
|
|
1950
1942
|
if(NIL_P(paramsData.params)) {
|
1951
1943
|
paramsData.params = rb_ary_new2(0);
|
@@ -1956,14 +1948,14 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1956
1948
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1957
1949
|
nParams = alloc_query_params( ¶msData );
|
1958
1950
|
|
1959
|
-
result = gvl_PQsendQueryPrepared(
|
1951
|
+
result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
|
1960
1952
|
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
|
1961
1953
|
resultFormat);
|
1962
1954
|
|
1963
1955
|
free_query_params( ¶msData );
|
1964
1956
|
|
1965
1957
|
if(result == 0) {
|
1966
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1958
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1967
1959
|
rb_iv_set(error, "@connection", self);
|
1968
1960
|
rb_exc_raise(error);
|
1969
1961
|
}
|
@@ -1981,10 +1973,10 @@ static VALUE
|
|
1981
1973
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
1982
1974
|
{
|
1983
1975
|
VALUE error;
|
1984
|
-
|
1976
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
1985
1977
|
/* returns 0 on failure */
|
1986
|
-
if(gvl_PQsendDescribePrepared(
|
1987
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
1978
|
+
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
|
1979
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
1988
1980
|
rb_iv_set(error, "@connection", self);
|
1989
1981
|
rb_exc_raise(error);
|
1990
1982
|
}
|
@@ -2003,10 +1995,10 @@ static VALUE
|
|
2003
1995
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2004
1996
|
{
|
2005
1997
|
VALUE error;
|
2006
|
-
|
1998
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2007
1999
|
/* returns 0 on failure */
|
2008
|
-
if(gvl_PQsendDescribePortal(
|
2009
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(
|
2000
|
+
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
|
2001
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
|
2010
2002
|
rb_iv_set(error, "@connection", self);
|
2011
2003
|
rb_exc_raise(error);
|
2012
2004
|
}
|
@@ -2177,7 +2169,6 @@ pgconn_flush(self)
|
|
2177
2169
|
static VALUE
|
2178
2170
|
pgconn_cancel(VALUE self)
|
2179
2171
|
{
|
2180
|
-
#ifdef HAVE_PQGETCANCEL
|
2181
2172
|
char errbuf[256];
|
2182
2173
|
PGcancel *cancel;
|
2183
2174
|
VALUE retval;
|
@@ -2195,9 +2186,6 @@ pgconn_cancel(VALUE self)
|
|
2195
2186
|
|
2196
2187
|
PQfreeCancel(cancel);
|
2197
2188
|
return retval;
|
2198
|
-
#else
|
2199
|
-
rb_notimplement();
|
2200
|
-
#endif
|
2201
2189
|
}
|
2202
2190
|
|
2203
2191
|
|
@@ -2211,7 +2199,7 @@ pgconn_cancel(VALUE self)
|
|
2211
2199
|
static VALUE
|
2212
2200
|
pgconn_notifies(VALUE self)
|
2213
2201
|
{
|
2214
|
-
|
2202
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2215
2203
|
PGnotify *notification;
|
2216
2204
|
VALUE hash;
|
2217
2205
|
VALUE sym_relname, sym_be_pid, sym_extra;
|
@@ -2221,17 +2209,17 @@ pgconn_notifies(VALUE self)
|
|
2221
2209
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2222
2210
|
sym_extra = ID2SYM(rb_intern("extra"));
|
2223
2211
|
|
2224
|
-
notification = gvl_PQnotifies(
|
2212
|
+
notification = gvl_PQnotifies(this->pgconn);
|
2225
2213
|
if (notification == NULL) {
|
2226
2214
|
return Qnil;
|
2227
2215
|
}
|
2228
2216
|
|
2229
2217
|
hash = rb_hash_new();
|
2230
|
-
relname =
|
2218
|
+
relname = rb_str_new2(notification->relname);
|
2231
2219
|
be_pid = INT2NUM(notification->be_pid);
|
2232
|
-
extra =
|
2233
|
-
PG_ENCODING_SET_NOCHECK( relname,
|
2234
|
-
PG_ENCODING_SET_NOCHECK( extra,
|
2220
|
+
extra = rb_str_new2(notification->extra);
|
2221
|
+
PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
|
2222
|
+
PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
|
2235
2223
|
|
2236
2224
|
rb_hash_aset(hash, sym_relname, relname);
|
2237
2225
|
rb_hash_aset(hash, sym_be_pid, be_pid);
|
@@ -2241,56 +2229,15 @@ pgconn_notifies(VALUE self)
|
|
2241
2229
|
return hash;
|
2242
2230
|
}
|
2243
2231
|
|
2244
|
-
/* Win32 + Ruby 1.
|
2245
|
-
#if
|
2246
|
-
|
2232
|
+
/* Win32 + Ruby 1.9+ */
|
2233
|
+
#if defined( _WIN32 )
|
2247
2234
|
/*
|
2248
|
-
*
|
2249
|
-
|
2250
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2251
|
-
{
|
2252
|
-
int i;
|
2253
|
-
crt_set->fd_count = os_set->fd_count;
|
2254
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2255
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2256
|
-
/* dupicate the SOCKET */
|
2257
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2258
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2259
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2260
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2261
|
-
os_set->fd_array[i] = s;
|
2262
|
-
crt_set->fd_array[i] = fd;
|
2263
|
-
}
|
2264
|
-
}
|
2265
|
-
|
2266
|
-
/*
|
2267
|
-
* Clean up the CRT FDs from create_crt_fd()
|
2268
|
-
*/
|
2269
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2270
|
-
{
|
2271
|
-
int i;
|
2272
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2273
|
-
/* cleanup the CRT fd */
|
2274
|
-
_close(crt_set->fd_array[i]);
|
2275
|
-
/* cleanup the duplicated SOCKET */
|
2276
|
-
closesocket(os_set->fd_array[i]);
|
2277
|
-
}
|
2278
|
-
}
|
2279
|
-
#endif
|
2280
|
-
|
2281
|
-
/* Win32 + Ruby 1.9+ */
|
2282
|
-
#if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
2283
|
-
/*
|
2284
|
-
* On Windows, use platform-specific strategies to wait for the socket
|
2285
|
-
* instead of rb_thread_select().
|
2235
|
+
* On Windows, use platform-specific strategies to wait for the socket
|
2236
|
+
* instead of rb_wait_for_single_fd().
|
2286
2237
|
*/
|
2287
2238
|
|
2288
2239
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2289
2240
|
|
2290
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2291
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2292
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2293
|
-
|
2294
2241
|
static void *
|
2295
2242
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
|
2296
2243
|
{
|
@@ -2367,7 +2314,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2367
2314
|
|
2368
2315
|
#else
|
2369
2316
|
|
2370
|
-
/* non Win32
|
2317
|
+
/* non Win32 */
|
2371
2318
|
|
2372
2319
|
static void *
|
2373
2320
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
@@ -2375,11 +2322,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2375
2322
|
int sd = PQsocket( conn );
|
2376
2323
|
int ret;
|
2377
2324
|
void *retval;
|
2378
|
-
rb_fdset_t sd_rset;
|
2379
2325
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2380
|
-
#ifdef _WIN32
|
2381
|
-
rb_fdset_t crt_sd_rset;
|
2382
|
-
#endif
|
2383
2326
|
|
2384
2327
|
if ( sd < 0 )
|
2385
2328
|
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
@@ -2388,25 +2331,12 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2388
2331
|
if ( PQconsumeInput(conn) == 0 )
|
2389
2332
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2390
2333
|
|
2391
|
-
rb_fd_init( &sd_rset );
|
2392
|
-
|
2393
2334
|
if ( ptimeout ) {
|
2394
2335
|
gettimeofday(&currtime, NULL);
|
2395
2336
|
timeradd(&currtime, ptimeout, &aborttime);
|
2396
2337
|
}
|
2397
2338
|
|
2398
2339
|
while ( !(retval=is_readable(conn)) ) {
|
2399
|
-
rb_fd_zero( &sd_rset );
|
2400
|
-
rb_fd_set( sd, &sd_rset );
|
2401
|
-
|
2402
|
-
#ifdef _WIN32
|
2403
|
-
/* Ruby's FD_SET is modified on win32 to convert a file descriptor
|
2404
|
-
* to osfhandle, but we already get a osfhandle from PQsocket().
|
2405
|
-
* Therefore it's overwritten here. */
|
2406
|
-
sd_rset.fd_array[0] = sd;
|
2407
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2408
|
-
#endif
|
2409
|
-
|
2410
2340
|
if ( ptimeout ) {
|
2411
2341
|
gettimeofday(&currtime, NULL);
|
2412
2342
|
timersub(&aborttime, &currtime, &waittime);
|
@@ -2415,35 +2345,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2415
2345
|
/* Is the given timeout valid? */
|
2416
2346
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2417
2347
|
/* Wait for the socket to become readable before checking again */
|
2418
|
-
ret =
|
2348
|
+
ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
|
2419
2349
|
} else {
|
2420
2350
|
ret = 0;
|
2421
2351
|
}
|
2422
2352
|
|
2423
|
-
|
2424
|
-
#ifdef _WIN32
|
2425
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2426
|
-
#endif
|
2427
|
-
|
2428
2353
|
if ( ret < 0 ){
|
2429
|
-
|
2430
|
-
rb_sys_fail( "rb_thread_select()" );
|
2354
|
+
rb_sys_fail( "rb_wait_for_single_fd()" );
|
2431
2355
|
}
|
2432
2356
|
|
2433
2357
|
/* Return false if the select() timed out */
|
2434
2358
|
if ( ret == 0 ){
|
2435
|
-
rb_fd_term( &sd_rset );
|
2436
2359
|
return NULL;
|
2437
2360
|
}
|
2438
2361
|
|
2439
2362
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2440
2363
|
if ( PQconsumeInput(conn) == 0 ){
|
2441
|
-
rb_fd_term( &sd_rset );
|
2442
2364
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2443
2365
|
}
|
2444
2366
|
}
|
2445
2367
|
|
2446
|
-
rb_fd_term( &sd_rset );
|
2447
2368
|
return retval;
|
2448
2369
|
}
|
2449
2370
|
|
@@ -2458,27 +2379,20 @@ notify_readable(PGconn *conn)
|
|
2458
2379
|
|
2459
2380
|
/*
|
2460
2381
|
* call-seq:
|
2461
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2462
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2463
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2382
|
+
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
|
2464
2383
|
*
|
2465
2384
|
* Blocks while waiting for notification(s), or until the optional
|
2466
2385
|
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2467
2386
|
* measured in seconds and can be fractional.
|
2468
2387
|
*
|
2469
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2470
|
-
*
|
2471
|
-
*
|
2472
|
-
*
|
2473
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2474
|
-
* the optional +payload+ string, it will be given to the block as the
|
2475
|
-
* third argument.
|
2476
|
-
*
|
2388
|
+
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
|
2389
|
+
* If used in block form, passes the name of the NOTIFY +event+, the generating
|
2390
|
+
* +pid+ and the optional +payload+ string into the block.
|
2477
2391
|
*/
|
2478
2392
|
static VALUE
|
2479
2393
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2480
2394
|
{
|
2481
|
-
|
2395
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2482
2396
|
PGnotify *pnotification;
|
2483
2397
|
struct timeval timeout;
|
2484
2398
|
struct timeval *ptimeout = NULL;
|
@@ -2494,20 +2408,18 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2494
2408
|
ptimeout = &timeout;
|
2495
2409
|
}
|
2496
2410
|
|
2497
|
-
pnotification = (PGnotify*) wait_socket_readable(
|
2411
|
+
pnotification = (PGnotify*) wait_socket_readable( this->pgconn, ptimeout, notify_readable);
|
2498
2412
|
|
2499
2413
|
/* Return nil if the select timed out */
|
2500
2414
|
if ( !pnotification ) return Qnil;
|
2501
2415
|
|
2502
|
-
relname =
|
2503
|
-
PG_ENCODING_SET_NOCHECK( relname,
|
2416
|
+
relname = rb_str_new2( pnotification->relname );
|
2417
|
+
PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
|
2504
2418
|
be_pid = INT2NUM( pnotification->be_pid );
|
2505
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2506
2419
|
if ( *pnotification->extra ) {
|
2507
|
-
extra =
|
2508
|
-
PG_ENCODING_SET_NOCHECK( extra,
|
2420
|
+
extra = rb_str_new2( pnotification->extra );
|
2421
|
+
PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
|
2509
2422
|
}
|
2510
|
-
#endif
|
2511
2423
|
PQfreemem( pnotification );
|
2512
2424
|
|
2513
2425
|
if ( rb_block_given_p() )
|
@@ -2526,9 +2438,10 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2526
2438
|
* not sent (false is only possible if the connection
|
2527
2439
|
* is in nonblocking mode, and this command would block).
|
2528
2440
|
*
|
2529
|
-
*
|
2530
|
-
* This encodes the
|
2531
|
-
*
|
2441
|
+
* _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
|
2442
|
+
* This encodes the data fields given as _buffer_ from an Array of Strings to
|
2443
|
+
* PostgreSQL's COPY text format inclusive proper escaping. Optionally
|
2444
|
+
* the encoder can type cast the fields from various Ruby types in one step,
|
2532
2445
|
* if PG::TextEncoder::CopyRow#type_map is set accordingly.
|
2533
2446
|
*
|
2534
2447
|
* Raises an exception if an error occurs.
|
@@ -2565,16 +2478,17 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2565
2478
|
|
2566
2479
|
if( p_coder ){
|
2567
2480
|
t_pg_coder_enc_func enc_func;
|
2481
|
+
int enc_idx = this->enc_idx;
|
2568
2482
|
|
2569
2483
|
enc_func = pg_coder_enc_func( p_coder );
|
2570
|
-
len = enc_func( p_coder, value, NULL, &intermediate );
|
2484
|
+
len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
|
2571
2485
|
|
2572
2486
|
if( len == -1 ){
|
2573
2487
|
/* The intermediate value is a String that can be used directly. */
|
2574
2488
|
buffer = intermediate;
|
2575
2489
|
} else {
|
2576
2490
|
buffer = rb_str_new(NULL, len);
|
2577
|
-
len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate);
|
2491
|
+
len = enc_func( p_coder, value, RSTRING_PTR(buffer), &intermediate, enc_idx);
|
2578
2492
|
rb_str_set_len( buffer, len );
|
2579
2493
|
}
|
2580
2494
|
}
|
@@ -2613,17 +2527,17 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2613
2527
|
VALUE str;
|
2614
2528
|
VALUE error;
|
2615
2529
|
int ret;
|
2616
|
-
char *error_message = NULL;
|
2617
|
-
|
2530
|
+
const char *error_message = NULL;
|
2531
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
2618
2532
|
|
2619
2533
|
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
2620
2534
|
error_message = NULL;
|
2621
2535
|
else
|
2622
|
-
error_message =
|
2536
|
+
error_message = pg_cstr_enc(str, this->enc_idx);
|
2623
2537
|
|
2624
|
-
ret = gvl_PQputCopyEnd(
|
2538
|
+
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
2625
2539
|
if(ret == -1) {
|
2626
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(
|
2540
|
+
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
|
2627
2541
|
rb_iv_set(error, "@connection", self);
|
2628
2542
|
rb_exc_raise(error);
|
2629
2543
|
}
|
@@ -2632,15 +2546,18 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2632
2546
|
|
2633
2547
|
/*
|
2634
2548
|
* call-seq:
|
2635
|
-
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) ->
|
2549
|
+
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
|
2636
2550
|
*
|
2637
|
-
* Return
|
2551
|
+
* Return one row of data, +nil+
|
2638
2552
|
* if the copy is done, or +false+ if the call would
|
2639
2553
|
* block (only possible if _async_ is true).
|
2640
2554
|
*
|
2641
|
-
*
|
2642
|
-
*
|
2643
|
-
*
|
2555
|
+
* If _decoder_ is not set or +nil+, data is returned as binary string.
|
2556
|
+
*
|
2557
|
+
* If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
|
2558
|
+
* PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
|
2559
|
+
* COPY text format to an Array of Strings.
|
2560
|
+
* Optionally the decoder can type cast the single fields to various Ruby types in one step,
|
2644
2561
|
* if PG::TextDecoder::CopyRow#type_map is set accordingly.
|
2645
2562
|
*
|
2646
2563
|
* See also #copy_data.
|
@@ -2686,9 +2603,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2686
2603
|
|
2687
2604
|
if( p_coder ){
|
2688
2605
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
|
2689
|
-
result = dec_func( p_coder, buffer, ret, 0, 0,
|
2606
|
+
result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
|
2690
2607
|
} else {
|
2691
|
-
result =
|
2608
|
+
result = rb_str_new(buffer, ret);
|
2692
2609
|
}
|
2693
2610
|
|
2694
2611
|
PQfreemem(buffer);
|
@@ -2697,13 +2614,20 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2697
2614
|
|
2698
2615
|
/*
|
2699
2616
|
* call-seq:
|
2700
|
-
* conn.set_error_verbosity( verbosity ) ->
|
2617
|
+
* conn.set_error_verbosity( verbosity ) -> Integer
|
2701
2618
|
*
|
2702
2619
|
* Sets connection's verbosity to _verbosity_ and returns
|
2703
2620
|
* the previous setting. Available settings are:
|
2621
|
+
*
|
2704
2622
|
* * PQERRORS_TERSE
|
2705
2623
|
* * PQERRORS_DEFAULT
|
2706
2624
|
* * PQERRORS_VERBOSE
|
2625
|
+
* * PQERRORS_SQLSTATE
|
2626
|
+
*
|
2627
|
+
* Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
|
2628
|
+
* (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
|
2629
|
+
*
|
2630
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
|
2707
2631
|
*/
|
2708
2632
|
static VALUE
|
2709
2633
|
pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
@@ -2713,6 +2637,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
|
2713
2637
|
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2714
2638
|
}
|
2715
2639
|
|
2640
|
+
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
2641
|
+
/*
|
2642
|
+
* call-seq:
|
2643
|
+
* conn.set_error_context_visibility( context_visibility ) -> Integer
|
2644
|
+
*
|
2645
|
+
* Sets connection's context display mode to _context_visibility_ and returns
|
2646
|
+
* the previous setting. Available settings are:
|
2647
|
+
* * PQSHOW_CONTEXT_NEVER
|
2648
|
+
* * PQSHOW_CONTEXT_ERRORS
|
2649
|
+
* * PQSHOW_CONTEXT_ALWAYS
|
2650
|
+
*
|
2651
|
+
* This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
|
2652
|
+
* The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
|
2653
|
+
* In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
|
2654
|
+
*
|
2655
|
+
* Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
|
2656
|
+
* (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
|
2657
|
+
*
|
2658
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
|
2659
|
+
*
|
2660
|
+
* Available since PostgreSQL-9.6
|
2661
|
+
*/
|
2662
|
+
static VALUE
|
2663
|
+
pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
|
2664
|
+
{
|
2665
|
+
PGconn *conn = pg_get_pgconn(self);
|
2666
|
+
PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
|
2667
|
+
return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
|
2668
|
+
}
|
2669
|
+
#endif
|
2670
|
+
|
2716
2671
|
/*
|
2717
2672
|
* call-seq:
|
2718
2673
|
* conn.trace( stream ) -> nil
|
@@ -2731,7 +2686,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2731
2686
|
VALUE new_file;
|
2732
2687
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2733
2688
|
|
2734
|
-
if(rb_respond_to(stream,rb_intern("fileno"))
|
2689
|
+
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2735
2690
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2736
2691
|
|
2737
2692
|
fileno = rb_funcall(stream, rb_intern("fileno"), 0);
|
@@ -2864,8 +2819,8 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2864
2819
|
t_pg_connection *this = pg_get_connection( self );
|
2865
2820
|
|
2866
2821
|
if (this->notice_receiver != Qnil) {
|
2867
|
-
VALUE message_str =
|
2868
|
-
PG_ENCODING_SET_NOCHECK( message_str,
|
2822
|
+
VALUE message_str = rb_str_new2(message);
|
2823
|
+
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2869
2824
|
rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
|
2870
2825
|
}
|
2871
2826
|
return;
|
@@ -2923,7 +2878,7 @@ static VALUE
|
|
2923
2878
|
pgconn_get_client_encoding(VALUE self)
|
2924
2879
|
{
|
2925
2880
|
char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
|
2926
|
-
return
|
2881
|
+
return rb_str_new2(encoding);
|
2927
2882
|
}
|
2928
2883
|
|
2929
2884
|
|
@@ -2940,12 +2895,10 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2940
2895
|
|
2941
2896
|
Check_Type(str, T_STRING);
|
2942
2897
|
|
2943
|
-
if ( (
|
2944
|
-
rb_raise(rb_ePGerror, "
|
2898
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
|
2899
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
2945
2900
|
}
|
2946
|
-
#ifdef M17N_SUPPORTED
|
2947
2901
|
pgconn_set_internal_encoding_index( self );
|
2948
|
-
#endif
|
2949
2902
|
|
2950
2903
|
return Qnil;
|
2951
2904
|
}
|
@@ -2996,10 +2949,10 @@ pgconn_transaction(VALUE self)
|
|
2996
2949
|
|
2997
2950
|
/*
|
2998
2951
|
* call-seq:
|
2999
|
-
* PG::Connection.quote_ident( str ) -> String
|
3000
|
-
* PG::Connection.quote_ident( array ) -> String
|
3001
2952
|
* conn.quote_ident( str ) -> String
|
3002
2953
|
* conn.quote_ident( array ) -> String
|
2954
|
+
* PG::Connection.quote_ident( str ) -> String
|
2955
|
+
* PG::Connection.quote_ident( array ) -> String
|
3003
2956
|
*
|
3004
2957
|
* Returns a string that is safe for inclusion in a SQL query as an
|
3005
2958
|
* identifier. Note: this is not a quote function for values, but for
|
@@ -3009,7 +2962,7 @@ pgconn_transaction(VALUE self)
|
|
3009
2962
|
* The identifier <tt>FOO</tt> is folded to lower case, so it actually
|
3010
2963
|
* means <tt>foo</tt>. If you really want to access the case-sensitive
|
3011
2964
|
* field name <tt>FOO</tt>, use this function like
|
3012
|
-
* <tt>
|
2965
|
+
* <tt>conn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
|
3013
2966
|
* (with double-quotes). PostgreSQL will see the double-quotes, and
|
3014
2967
|
* it will not fold to lower case.
|
3015
2968
|
*
|
@@ -3023,15 +2976,25 @@ pgconn_transaction(VALUE self)
|
|
3023
2976
|
*
|
3024
2977
|
* This method is functional identical to the encoder PG::TextEncoder::Identifier .
|
3025
2978
|
*
|
2979
|
+
* If the instance method form is used and the input string character encoding
|
2980
|
+
* is different to the connection encoding, then the string is converted to this
|
2981
|
+
* encoding, so that the returned string is always encoded as PG::Connection#internal_encoding .
|
2982
|
+
*
|
2983
|
+
* In the singleton form (PG::Connection.quote_ident) the character encoding
|
2984
|
+
* of the result string is set to the character encoding of the input string.
|
3026
2985
|
*/
|
3027
2986
|
static VALUE
|
3028
|
-
pgconn_s_quote_ident(VALUE self, VALUE
|
2987
|
+
pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
|
3029
2988
|
{
|
3030
2989
|
VALUE ret;
|
3031
|
-
|
2990
|
+
int enc_idx;
|
3032
2991
|
|
3033
|
-
|
3034
|
-
|
2992
|
+
if( rb_obj_is_kind_of(self, rb_cPGconn) ){
|
2993
|
+
enc_idx = pg_get_connection(self)->enc_idx;
|
2994
|
+
}else{
|
2995
|
+
enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
|
2996
|
+
}
|
2997
|
+
pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
|
3035
2998
|
|
3036
2999
|
return ret;
|
3037
3000
|
}
|
@@ -3061,10 +3024,6 @@ static VALUE
|
|
3061
3024
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
3062
3025
|
PGconn *conn = pg_get_pgconn( self );
|
3063
3026
|
|
3064
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
3065
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
3066
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
3067
|
-
|
3068
3027
|
struct timeval timeout;
|
3069
3028
|
struct timeval *ptimeout = NULL;
|
3070
3029
|
VALUE timeout_in;
|
@@ -3131,24 +3090,181 @@ pgconn_get_last_result(VALUE self)
|
|
3131
3090
|
|
3132
3091
|
/*
|
3133
3092
|
* call-seq:
|
3134
|
-
* conn.
|
3135
|
-
*
|
3093
|
+
* conn.discard_results()
|
3094
|
+
*
|
3095
|
+
* Silently discard any prior query result that application didn't eat.
|
3096
|
+
* This is done prior of Connection#exec and sibling methods and can
|
3097
|
+
* be called explicitly when using the async API.
|
3098
|
+
*/
|
3099
|
+
static VALUE
|
3100
|
+
pgconn_discard_results(VALUE self)
|
3101
|
+
{
|
3102
|
+
PGconn *conn = pg_get_pgconn(self);
|
3103
|
+
|
3104
|
+
PGresult *cur;
|
3105
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3106
|
+
int status = PQresultStatus(cur);
|
3107
|
+
PQclear(cur);
|
3108
|
+
if (status == PGRES_COPY_IN){
|
3109
|
+
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3110
|
+
}
|
3111
|
+
if (status == PGRES_COPY_OUT){
|
3112
|
+
char *buffer = NULL;
|
3113
|
+
while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
|
3114
|
+
PQfreemem(buffer);
|
3115
|
+
}
|
3116
|
+
}
|
3117
|
+
|
3118
|
+
return Qnil;
|
3119
|
+
}
|
3120
|
+
|
3121
|
+
/*
|
3122
|
+
* call-seq:
|
3123
|
+
* conn.exec(sql) -> PG::Result
|
3124
|
+
* conn.exec(sql) {|pg_result| block }
|
3125
|
+
*
|
3126
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
3127
|
+
* On success, it returns a PG::Result instance with all result rows and columns.
|
3128
|
+
* On failure, it raises a PG::Error.
|
3129
|
+
*
|
3130
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
3131
|
+
* it will call #exec_params for you. New code should explicitly use #exec_params if
|
3132
|
+
* argument placeholders are used.
|
3136
3133
|
*
|
3137
|
-
*
|
3138
|
-
*
|
3139
|
-
*
|
3134
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3135
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3136
|
+
* In this instance, <code>conn.exec</code> returns the value of the block.
|
3137
|
+
*
|
3138
|
+
* #exec is an alias for #async_exec which is almost identical to #sync_exec .
|
3139
|
+
* #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
|
3140
|
+
* #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
|
3141
|
+
* Both methods ensure that other threads can process while waiting for the server to
|
3142
|
+
* complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
|
3143
|
+
* This is most notably visible by a delayed reaction to Control+C.
|
3144
|
+
* It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
|
3145
|
+
*
|
3146
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
|
3140
3147
|
*/
|
3141
3148
|
static VALUE
|
3142
3149
|
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
3143
3150
|
{
|
3144
3151
|
VALUE rb_pgresult = Qnil;
|
3145
3152
|
|
3146
|
-
|
3153
|
+
pgconn_discard_results( self );
|
3154
|
+
pgconn_send_query( argc, argv, self );
|
3147
3155
|
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3148
|
-
pgconn_get_last_result( self );
|
3156
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3149
3157
|
|
3150
|
-
|
3151
|
-
|
3158
|
+
if ( rb_block_given_p() ) {
|
3159
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3160
|
+
}
|
3161
|
+
return rb_pgresult;
|
3162
|
+
}
|
3163
|
+
|
3164
|
+
|
3165
|
+
/*
|
3166
|
+
* call-seq:
|
3167
|
+
* conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
|
3168
|
+
* conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
|
3169
|
+
*
|
3170
|
+
* Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
|
3171
|
+
* for parameters.
|
3172
|
+
*
|
3173
|
+
* Returns a PG::Result instance on success. On failure, it raises a PG::Error.
|
3174
|
+
*
|
3175
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
3176
|
+
* Each element of the +params+ array may be either:
|
3177
|
+
* a hash of the form:
|
3178
|
+
* {:value => String (value of bind parameter)
|
3179
|
+
* :type => Integer (oid of type of bind parameter)
|
3180
|
+
* :format => Integer (0 for text, 1 for binary)
|
3181
|
+
* }
|
3182
|
+
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3183
|
+
* { :value => <string value>, :type => 0, :format => 0 }
|
3184
|
+
*
|
3185
|
+
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
3186
|
+
* inside the SQL query. The 0th element of the +params+ array is bound
|
3187
|
+
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3188
|
+
*
|
3189
|
+
* If the types are not specified, they will be inferred by PostgreSQL.
|
3190
|
+
* Instead of specifying type oids, it's recommended to simply add
|
3191
|
+
* explicit casts in the query to ensure that the right type is used.
|
3192
|
+
*
|
3193
|
+
* For example: "SELECT $1::int"
|
3194
|
+
*
|
3195
|
+
* The optional +result_format+ should be 0 for text results, 1
|
3196
|
+
* for binary.
|
3197
|
+
*
|
3198
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
3199
|
+
* This will type cast the params from various Ruby types before transmission
|
3200
|
+
* based on the encoders defined by the type map. When a type encoder is used
|
3201
|
+
* the format and oid of a given bind parameter are retrieved from the encoder
|
3202
|
+
* instead out of the hash form described above.
|
3203
|
+
*
|
3204
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3205
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3206
|
+
* In this instance, <code>conn.exec</code> returns the value of the block.
|
3207
|
+
*
|
3208
|
+
* The primary advantage of #exec_params over #exec is that parameter values can be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping.
|
3209
|
+
* Unlike #exec, #exec_params allows at most one SQL command in the given string.
|
3210
|
+
* (There can be semicolons in it, but not more than one nonempty command.)
|
3211
|
+
* This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
|
3212
|
+
*
|
3213
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
|
3214
|
+
*/
|
3215
|
+
static VALUE
|
3216
|
+
pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
3217
|
+
{
|
3218
|
+
VALUE rb_pgresult = Qnil;
|
3219
|
+
|
3220
|
+
pgconn_discard_results( self );
|
3221
|
+
/* If called with no or nil parameters, use PQsendQuery for compatibility */
|
3222
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
3223
|
+
pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
|
3224
|
+
pgconn_send_query( argc, argv, self );
|
3225
|
+
} else {
|
3226
|
+
pgconn_send_query_params( argc, argv, self );
|
3227
|
+
}
|
3228
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3229
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3230
|
+
|
3231
|
+
if ( rb_block_given_p() ) {
|
3232
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3233
|
+
}
|
3234
|
+
return rb_pgresult;
|
3235
|
+
}
|
3236
|
+
|
3237
|
+
|
3238
|
+
/*
|
3239
|
+
* call-seq:
|
3240
|
+
* conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
3241
|
+
*
|
3242
|
+
* Prepares statement _sql_ with name _name_ to be executed later.
|
3243
|
+
* Returns a PG::Result instance on success.
|
3244
|
+
* On failure, it raises a PG::Error.
|
3245
|
+
*
|
3246
|
+
* +param_types+ is an optional parameter to specify the Oids of the
|
3247
|
+
* types of the parameters.
|
3248
|
+
*
|
3249
|
+
* If the types are not specified, they will be inferred by PostgreSQL.
|
3250
|
+
* Instead of specifying type oids, it's recommended to simply add
|
3251
|
+
* explicit casts in the query to ensure that the right type is used.
|
3252
|
+
*
|
3253
|
+
* For example: "SELECT $1::int"
|
3254
|
+
*
|
3255
|
+
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
3256
|
+
* inside the SQL query.
|
3257
|
+
*
|
3258
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
|
3259
|
+
*/
|
3260
|
+
static VALUE
|
3261
|
+
pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
3262
|
+
{
|
3263
|
+
VALUE rb_pgresult = Qnil;
|
3264
|
+
|
3265
|
+
pgconn_discard_results( self );
|
3266
|
+
pgconn_send_prepare( argc, argv, self );
|
3267
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3152
3268
|
rb_pgresult = pgconn_get_last_result( self );
|
3153
3269
|
|
3154
3270
|
if ( rb_block_given_p() ) {
|
@@ -3157,13 +3273,197 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3157
3273
|
return rb_pgresult;
|
3158
3274
|
}
|
3159
3275
|
|
3276
|
+
|
3277
|
+
/*
|
3278
|
+
* call-seq:
|
3279
|
+
* conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
3280
|
+
* conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
3281
|
+
*
|
3282
|
+
* Execute prepared named statement specified by _statement_name_.
|
3283
|
+
* Returns a PG::Result instance on success.
|
3284
|
+
* On failure, it raises a PG::Error.
|
3285
|
+
*
|
3286
|
+
* +params+ is an array of the optional bind parameters for the
|
3287
|
+
* SQL query. Each element of the +params+ array may be either:
|
3288
|
+
* a hash of the form:
|
3289
|
+
* {:value => String (value of bind parameter)
|
3290
|
+
* :format => Integer (0 for text, 1 for binary)
|
3291
|
+
* }
|
3292
|
+
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
3293
|
+
* { :value => <string value>, :format => 0 }
|
3294
|
+
*
|
3295
|
+
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
3296
|
+
* inside the SQL query. The 0th element of the +params+ array is bound
|
3297
|
+
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
3298
|
+
*
|
3299
|
+
* The optional +result_format+ should be 0 for text results, 1
|
3300
|
+
* for binary.
|
3301
|
+
*
|
3302
|
+
* +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
3303
|
+
* This will type cast the params from various Ruby types before transmission
|
3304
|
+
* based on the encoders defined by the type map. When a type encoder is used
|
3305
|
+
* the format and oid of a given bind parameter are retrieved from the encoder
|
3306
|
+
* instead out of the hash form described above.
|
3307
|
+
*
|
3308
|
+
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
3309
|
+
* and the PG::Result object will automatically be cleared when the block terminates.
|
3310
|
+
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
3311
|
+
*
|
3312
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
|
3313
|
+
*/
|
3314
|
+
static VALUE
|
3315
|
+
pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
3316
|
+
{
|
3317
|
+
VALUE rb_pgresult = Qnil;
|
3318
|
+
|
3319
|
+
pgconn_discard_results( self );
|
3320
|
+
pgconn_send_query_prepared( argc, argv, self );
|
3321
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3322
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3323
|
+
|
3324
|
+
if ( rb_block_given_p() ) {
|
3325
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3326
|
+
}
|
3327
|
+
return rb_pgresult;
|
3328
|
+
}
|
3329
|
+
|
3330
|
+
|
3331
|
+
/*
|
3332
|
+
* call-seq:
|
3333
|
+
* conn.describe_portal( portal_name ) -> PG::Result
|
3334
|
+
*
|
3335
|
+
* Retrieve information about the portal _portal_name_.
|
3336
|
+
*
|
3337
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
|
3338
|
+
*/
|
3339
|
+
static VALUE
|
3340
|
+
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3341
|
+
{
|
3342
|
+
VALUE rb_pgresult = Qnil;
|
3343
|
+
|
3344
|
+
pgconn_discard_results( self );
|
3345
|
+
pgconn_send_describe_portal( self, portal );
|
3346
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3347
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3348
|
+
|
3349
|
+
if ( rb_block_given_p() ) {
|
3350
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3351
|
+
}
|
3352
|
+
return rb_pgresult;
|
3353
|
+
}
|
3354
|
+
|
3355
|
+
|
3356
|
+
/*
|
3357
|
+
* call-seq:
|
3358
|
+
* conn.describe_prepared( statement_name ) -> PG::Result
|
3359
|
+
*
|
3360
|
+
* Retrieve information about the prepared statement _statement_name_.
|
3361
|
+
*
|
3362
|
+
* See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
|
3363
|
+
*/
|
3364
|
+
static VALUE
|
3365
|
+
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3366
|
+
{
|
3367
|
+
VALUE rb_pgresult = Qnil;
|
3368
|
+
|
3369
|
+
pgconn_discard_results( self );
|
3370
|
+
pgconn_send_describe_prepared( self, stmt_name );
|
3371
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3372
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3373
|
+
|
3374
|
+
if ( rb_block_given_p() ) {
|
3375
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3376
|
+
}
|
3377
|
+
return rb_pgresult;
|
3378
|
+
}
|
3379
|
+
|
3380
|
+
|
3381
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
3382
|
+
/*
|
3383
|
+
* call-seq:
|
3384
|
+
* conn.ssl_in_use? -> Boolean
|
3385
|
+
*
|
3386
|
+
* Returns +true+ if the connection uses SSL/TLS, +false+ if not.
|
3387
|
+
*
|
3388
|
+
* Available since PostgreSQL-9.5
|
3389
|
+
*/
|
3390
|
+
static VALUE
|
3391
|
+
pgconn_ssl_in_use(VALUE self)
|
3392
|
+
{
|
3393
|
+
return PQsslInUse(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
3394
|
+
}
|
3395
|
+
|
3396
|
+
|
3397
|
+
/*
|
3398
|
+
* call-seq:
|
3399
|
+
* conn.ssl_attribute(attribute_name) -> String
|
3400
|
+
*
|
3401
|
+
* Returns SSL-related information about the connection.
|
3402
|
+
*
|
3403
|
+
* The list of available attributes varies depending on the SSL library being used,
|
3404
|
+
* and the type of connection. If an attribute is not available, returns nil.
|
3405
|
+
*
|
3406
|
+
* The following attributes are commonly available:
|
3407
|
+
*
|
3408
|
+
* [+library+]
|
3409
|
+
* Name of the SSL implementation in use. (Currently, only "OpenSSL" is implemented)
|
3410
|
+
* [+protocol+]
|
3411
|
+
* SSL/TLS version in use. Common values are "SSLv2", "SSLv3", "TLSv1", "TLSv1.1" and "TLSv1.2", but an implementation may return other strings if some other protocol is used.
|
3412
|
+
* [+key_bits+]
|
3413
|
+
* Number of key bits used by the encryption algorithm.
|
3414
|
+
* [+cipher+]
|
3415
|
+
* A short name of the ciphersuite used, e.g. "DHE-RSA-DES-CBC3-SHA". The names are specific to each SSL implementation.
|
3416
|
+
* [+compression+]
|
3417
|
+
* If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
|
3418
|
+
*
|
3419
|
+
*
|
3420
|
+
* See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
|
3421
|
+
*
|
3422
|
+
* Available since PostgreSQL-9.5
|
3423
|
+
*/
|
3424
|
+
static VALUE
|
3425
|
+
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
3426
|
+
{
|
3427
|
+
const char *p_attr;
|
3428
|
+
|
3429
|
+
p_attr = PQsslAttribute(pg_get_pgconn(self), StringValueCStr(attribute_name));
|
3430
|
+
return p_attr ? rb_str_new_cstr(p_attr) : Qnil;
|
3431
|
+
}
|
3432
|
+
|
3433
|
+
/*
|
3434
|
+
* call-seq:
|
3435
|
+
* conn.ssl_attribute_names -> Array<String>
|
3436
|
+
*
|
3437
|
+
* Return an array of SSL attribute names available.
|
3438
|
+
*
|
3439
|
+
* See also #ssl_attribute
|
3440
|
+
*
|
3441
|
+
* Available since PostgreSQL-9.5
|
3442
|
+
*/
|
3443
|
+
static VALUE
|
3444
|
+
pgconn_ssl_attribute_names(VALUE self)
|
3445
|
+
{
|
3446
|
+
int i;
|
3447
|
+
const char * const * p_list = PQsslAttributeNames(pg_get_pgconn(self));
|
3448
|
+
VALUE ary = rb_ary_new();
|
3449
|
+
|
3450
|
+
for ( i = 0; p_list[i]; i++ ) {
|
3451
|
+
rb_ary_push( ary, rb_str_new_cstr( p_list[i] ));
|
3452
|
+
}
|
3453
|
+
return ary;
|
3454
|
+
}
|
3455
|
+
|
3456
|
+
|
3457
|
+
#endif
|
3458
|
+
|
3459
|
+
|
3160
3460
|
/**************************************************************************
|
3161
3461
|
* LARGE OBJECT SUPPORT
|
3162
3462
|
**************************************************************************/
|
3163
3463
|
|
3164
3464
|
/*
|
3165
3465
|
* call-seq:
|
3166
|
-
* conn.lo_creat( [mode] ) ->
|
3466
|
+
* conn.lo_creat( [mode] ) -> Integer
|
3167
3467
|
*
|
3168
3468
|
* Creates a large object with mode _mode_. Returns a large object Oid.
|
3169
3469
|
* On failure, it raises PG::Error.
|
@@ -3190,7 +3490,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
3190
3490
|
|
3191
3491
|
/*
|
3192
3492
|
* call-seq:
|
3193
|
-
* conn.lo_create( oid ) ->
|
3493
|
+
* conn.lo_create( oid ) -> Integer
|
3194
3494
|
*
|
3195
3495
|
* Creates a large object with oid _oid_. Returns the large object Oid.
|
3196
3496
|
* On failure, it raises PG::Error.
|
@@ -3211,7 +3511,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
3211
3511
|
|
3212
3512
|
/*
|
3213
3513
|
* call-seq:
|
3214
|
-
* conn.lo_import(file) ->
|
3514
|
+
* conn.lo_import(file) -> Integer
|
3215
3515
|
*
|
3216
3516
|
* Import a file to a large object. Returns a large object Oid.
|
3217
3517
|
*
|
@@ -3256,7 +3556,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
3256
3556
|
|
3257
3557
|
/*
|
3258
3558
|
* call-seq:
|
3259
|
-
* conn.lo_open( oid, [mode] ) ->
|
3559
|
+
* conn.lo_open( oid, [mode] ) -> Integer
|
3260
3560
|
*
|
3261
3561
|
* Open a large object of _oid_. Returns a large object descriptor
|
3262
3562
|
* instance on success. The _mode_ argument specifies the mode for
|
@@ -3287,7 +3587,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
3287
3587
|
|
3288
3588
|
/*
|
3289
3589
|
* call-seq:
|
3290
|
-
* conn.lo_write( lo_desc, buffer ) ->
|
3590
|
+
* conn.lo_write( lo_desc, buffer ) -> Integer
|
3291
3591
|
*
|
3292
3592
|
* Writes the string _buffer_ to the large object _lo_desc_.
|
3293
3593
|
* Returns the number of bytes written.
|
@@ -3345,7 +3645,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3345
3645
|
return Qnil;
|
3346
3646
|
}
|
3347
3647
|
|
3348
|
-
str =
|
3648
|
+
str = rb_str_new(buffer, ret);
|
3349
3649
|
xfree(buffer);
|
3350
3650
|
|
3351
3651
|
return str;
|
@@ -3354,7 +3654,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3354
3654
|
|
3355
3655
|
/*
|
3356
3656
|
* call-seq:
|
3357
|
-
* conn.lo_lseek( lo_desc, offset, whence ) ->
|
3657
|
+
* conn.lo_lseek( lo_desc, offset, whence ) -> Integer
|
3358
3658
|
*
|
3359
3659
|
* Move the large object pointer _lo_desc_ to offset _offset_.
|
3360
3660
|
* Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
|
@@ -3376,7 +3676,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
3376
3676
|
|
3377
3677
|
/*
|
3378
3678
|
* call-seq:
|
3379
|
-
* conn.lo_tell( lo_desc ) ->
|
3679
|
+
* conn.lo_tell( lo_desc ) -> Integer
|
3380
3680
|
*
|
3381
3681
|
* Returns the current position of the large object _lo_desc_.
|
3382
3682
|
*/
|
@@ -3449,14 +3749,15 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3449
3749
|
}
|
3450
3750
|
|
3451
3751
|
|
3452
|
-
|
3453
|
-
|
3454
|
-
void
|
3752
|
+
static void
|
3455
3753
|
pgconn_set_internal_encoding_index( VALUE self )
|
3456
3754
|
{
|
3457
|
-
|
3458
|
-
|
3459
|
-
|
3755
|
+
int enc_idx;
|
3756
|
+
t_pg_connection *this = pg_get_connection_safe( self );
|
3757
|
+
rb_encoding *enc = pg_conn_enc_get( this->pgconn );
|
3758
|
+
enc_idx = rb_enc_to_index(enc);
|
3759
|
+
if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
|
3760
|
+
this->enc_idx = enc_idx;
|
3460
3761
|
}
|
3461
3762
|
|
3462
3763
|
/*
|
@@ -3499,7 +3800,6 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
3499
3800
|
static VALUE
|
3500
3801
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3501
3802
|
{
|
3502
|
-
VALUE enc_inspect;
|
3503
3803
|
if (NIL_P(enc)) {
|
3504
3804
|
pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3505
3805
|
return enc;
|
@@ -3512,7 +3812,7 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3512
3812
|
rb_encoding *rbenc = rb_to_encoding( enc );
|
3513
3813
|
const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
|
3514
3814
|
|
3515
|
-
if (
|
3815
|
+
if ( gvl_PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
|
3516
3816
|
VALUE server_encoding = pgconn_external_encoding( self );
|
3517
3817
|
rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
|
3518
3818
|
rb_enc_name(rb_to_encoding(server_encoding)), name );
|
@@ -3520,11 +3820,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3520
3820
|
pgconn_set_internal_encoding_index( self );
|
3521
3821
|
return enc;
|
3522
3822
|
}
|
3523
|
-
|
3524
|
-
enc_inspect = rb_inspect(enc);
|
3525
|
-
rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
|
3526
|
-
|
3527
|
-
return Qnil;
|
3528
3823
|
}
|
3529
3824
|
|
3530
3825
|
|
@@ -3543,17 +3838,41 @@ pgconn_external_encoding(VALUE self)
|
|
3543
3838
|
rb_encoding *enc = NULL;
|
3544
3839
|
const char *pg_encname = NULL;
|
3545
3840
|
|
3546
|
-
/* Use cached value if found */
|
3547
|
-
if ( RTEST(this->external_encoding) ) return this->external_encoding;
|
3548
|
-
|
3549
3841
|
pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
|
3550
3842
|
enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
|
3551
|
-
|
3843
|
+
return rb_enc_from_encoding( enc );
|
3844
|
+
}
|
3845
|
+
|
3846
|
+
|
3847
|
+
static VALUE
|
3848
|
+
pgconn_set_client_encoding_async1( VALUE args )
|
3849
|
+
{
|
3850
|
+
VALUE self = ((VALUE*)args)[0];
|
3851
|
+
VALUE encname = ((VALUE*)args)[1];
|
3852
|
+
VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
3853
|
+
VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
3854
|
+
|
3855
|
+
pgconn_async_exec(1, &query, self);
|
3856
|
+
return 0;
|
3857
|
+
}
|
3858
|
+
|
3552
3859
|
|
3553
|
-
|
3860
|
+
static VALUE
|
3861
|
+
pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
|
3862
|
+
{
|
3863
|
+
UNUSED(arg);
|
3864
|
+
UNUSED(ex);
|
3865
|
+
return 1;
|
3554
3866
|
}
|
3555
3867
|
|
3556
3868
|
|
3869
|
+
static VALUE
|
3870
|
+
pgconn_set_client_encoding_async( VALUE self, const char *encname )
|
3871
|
+
{
|
3872
|
+
VALUE args[] = { self, rb_str_new_cstr(encname) };
|
3873
|
+
return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
|
3874
|
+
}
|
3875
|
+
|
3557
3876
|
|
3558
3877
|
/*
|
3559
3878
|
* call-seq:
|
@@ -3572,8 +3891,8 @@ pgconn_set_default_encoding( VALUE self )
|
|
3572
3891
|
|
3573
3892
|
if (( enc = rb_default_internal_encoding() )) {
|
3574
3893
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3575
|
-
if (
|
3576
|
-
|
3894
|
+
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
3895
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3577
3896
|
encname, PQerrorMessage(conn) );
|
3578
3897
|
pgconn_set_internal_encoding_index( self );
|
3579
3898
|
return rb_enc_from_encoding( enc );
|
@@ -3584,8 +3903,6 @@ pgconn_set_default_encoding( VALUE self )
|
|
3584
3903
|
}
|
3585
3904
|
|
3586
3905
|
|
3587
|
-
#endif /* M17N_SUPPORTED */
|
3588
|
-
|
3589
3906
|
/*
|
3590
3907
|
* call-seq:
|
3591
3908
|
* res.type_map_for_queries = typemap
|
@@ -3704,7 +4021,7 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
|
|
3704
4021
|
*
|
3705
4022
|
* Returns either:
|
3706
4023
|
* * a kind of PG::Coder
|
3707
|
-
* * +nil+ - type encoding is disabled,
|
4024
|
+
* * +nil+ - type encoding is disabled, data must be a String.
|
3708
4025
|
*
|
3709
4026
|
*/
|
3710
4027
|
static VALUE
|
@@ -3764,7 +4081,62 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
3764
4081
|
return this->decoder_for_get_copy_data;
|
3765
4082
|
}
|
3766
4083
|
|
4084
|
+
/*
|
4085
|
+
* call-seq:
|
4086
|
+
* conn.field_name_type = Symbol
|
4087
|
+
*
|
4088
|
+
* Set default type of field names of results retrieved by this connection.
|
4089
|
+
* It can be set to one of:
|
4090
|
+
* * +:string+ to use String based field names
|
4091
|
+
* * +:symbol+ to use Symbol based field names
|
4092
|
+
*
|
4093
|
+
* The default is +:string+ .
|
4094
|
+
*
|
4095
|
+
* Settings the type of field names affects only future results.
|
4096
|
+
*
|
4097
|
+
* See further description at PG::Result#field_name_type=
|
4098
|
+
*
|
4099
|
+
*/
|
4100
|
+
static VALUE
|
4101
|
+
pgconn_field_name_type_set(VALUE self, VALUE sym)
|
4102
|
+
{
|
4103
|
+
t_pg_connection *this = pg_get_connection( self );
|
4104
|
+
|
4105
|
+
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4106
|
+
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4107
|
+
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
4108
|
+
else if ( sym == sym_string );
|
4109
|
+
else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
|
4110
|
+
|
4111
|
+
return sym;
|
4112
|
+
}
|
4113
|
+
|
4114
|
+
/*
|
4115
|
+
* call-seq:
|
4116
|
+
* conn.field_name_type -> Symbol
|
4117
|
+
*
|
4118
|
+
* Get type of field names.
|
4119
|
+
*
|
4120
|
+
* See description at #field_name_type=
|
4121
|
+
*/
|
4122
|
+
static VALUE
|
4123
|
+
pgconn_field_name_type_get(VALUE self)
|
4124
|
+
{
|
4125
|
+
t_pg_connection *this = pg_get_connection( self );
|
4126
|
+
|
4127
|
+
if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
|
4128
|
+
return sym_symbol;
|
4129
|
+
} else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
|
4130
|
+
return sym_static_symbol;
|
4131
|
+
} else {
|
4132
|
+
return sym_string;
|
4133
|
+
}
|
4134
|
+
}
|
4135
|
+
|
3767
4136
|
|
4137
|
+
/*
|
4138
|
+
* Document-class: PG::Connection
|
4139
|
+
*/
|
3768
4140
|
void
|
3769
4141
|
init_pg_connection()
|
3770
4142
|
{
|
@@ -3772,8 +4144,13 @@ init_pg_connection()
|
|
3772
4144
|
sym_type = ID2SYM(rb_intern("type"));
|
3773
4145
|
sym_format = ID2SYM(rb_intern("format"));
|
3774
4146
|
sym_value = ID2SYM(rb_intern("value"));
|
4147
|
+
sym_string = ID2SYM(rb_intern("string"));
|
4148
|
+
sym_symbol = ID2SYM(rb_intern("symbol"));
|
4149
|
+
sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
|
3775
4150
|
|
3776
4151
|
rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
|
4152
|
+
/* Help rdoc to known the Constants module */
|
4153
|
+
/* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
|
3777
4154
|
rb_include_module(rb_cPGconn, rb_mPGconstants);
|
3778
4155
|
|
3779
4156
|
/****** PG::Connection CLASS METHODS ******/
|
@@ -3791,9 +4168,7 @@ init_pg_connection()
|
|
3791
4168
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3792
4169
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
3793
4170
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
3794
|
-
#ifdef HAVE_PQPING
|
3795
4171
|
rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
|
3796
|
-
#endif
|
3797
4172
|
|
3798
4173
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
3799
4174
|
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
@@ -3823,39 +4198,47 @@ init_pg_connection()
|
|
3823
4198
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
3824
4199
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
3825
4200
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
3826
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
3827
4201
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
3828
|
-
#endif
|
3829
4202
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
3830
4203
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
3831
4204
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
3832
4205
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
3833
4206
|
|
3834
4207
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
3835
|
-
rb_define_method(rb_cPGconn, "
|
3836
|
-
|
3837
|
-
rb_define_method(rb_cPGconn, "
|
3838
|
-
rb_define_method(rb_cPGconn, "
|
3839
|
-
rb_define_method(rb_cPGconn, "
|
3840
|
-
rb_define_method(rb_cPGconn, "
|
3841
|
-
|
4208
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
|
4209
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
|
4210
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
|
4211
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
|
4212
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
|
4213
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
|
4214
|
+
|
4215
|
+
rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
|
4216
|
+
rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
|
4217
|
+
rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
|
4218
|
+
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
|
4219
|
+
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
|
4220
|
+
rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
|
4221
|
+
|
4222
|
+
rb_define_alias(rb_cPGconn, "async_exec", "exec");
|
4223
|
+
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4224
|
+
rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
|
4225
|
+
rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
|
4226
|
+
rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
|
4227
|
+
rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
|
4228
|
+
rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
|
4229
|
+
|
3842
4230
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
3843
4231
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
3844
4232
|
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
3845
|
-
#ifdef HAVE_PQESCAPELITERAL
|
3846
4233
|
rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
|
3847
|
-
#endif
|
3848
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
3849
4234
|
rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
|
3850
|
-
#endif
|
3851
4235
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
3852
4236
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
3853
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
3854
4237
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
3855
|
-
#endif
|
3856
4238
|
|
3857
4239
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
3858
4240
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4241
|
+
rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
|
3859
4242
|
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
3860
4243
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
3861
4244
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
@@ -3867,6 +4250,7 @@ init_pg_connection()
|
|
3867
4250
|
rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
|
3868
4251
|
rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
|
3869
4252
|
rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
|
4253
|
+
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
3870
4254
|
|
3871
4255
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
3872
4256
|
rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
|
@@ -3881,6 +4265,9 @@ init_pg_connection()
|
|
3881
4265
|
|
3882
4266
|
/****** PG::Connection INSTANCE METHODS: Control Functions ******/
|
3883
4267
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4268
|
+
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
4269
|
+
rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
|
4270
|
+
#endif
|
3884
4271
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
3885
4272
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
3886
4273
|
|
@@ -3897,9 +4284,16 @@ init_pg_connection()
|
|
3897
4284
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
3898
4285
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
3899
4286
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3900
|
-
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
3901
|
-
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
3902
4287
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
4288
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4289
|
+
rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
|
4290
|
+
#endif
|
4291
|
+
|
4292
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
4293
|
+
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
4294
|
+
rb_define_method(rb_cPGconn, "ssl_attribute", pgconn_ssl_attribute, 1);
|
4295
|
+
rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
|
4296
|
+
#endif
|
3903
4297
|
|
3904
4298
|
/****** PG::Connection INSTANCE METHODS: Large Object Support ******/
|
3905
4299
|
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
@@ -3929,12 +4323,10 @@ init_pg_connection()
|
|
3929
4323
|
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
3930
4324
|
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
3931
4325
|
|
3932
|
-
#ifdef M17N_SUPPORTED
|
3933
4326
|
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
3934
4327
|
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
3935
4328
|
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
3936
4329
|
rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
|
3937
|
-
#endif /* M17N_SUPPORTED */
|
3938
4330
|
|
3939
4331
|
rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
|
3940
4332
|
rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
|
@@ -3944,5 +4336,7 @@ init_pg_connection()
|
|
3944
4336
|
rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
|
3945
4337
|
rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
|
3946
4338
|
rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
|
3947
|
-
}
|
3948
4339
|
|
4340
|
+
rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
|
4341
|
+
rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
|
4342
|
+
}
|