pg 0.21.0 → 1.1.4
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/History.rdoc +98 -0
- data/Manifest.txt +5 -1
- data/README.rdoc +14 -4
- data/Rakefile +4 -5
- data/Rakefile.cross +17 -21
- data/ext/errorcodes.def +12 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +4 -1
- data/ext/extconf.rb +14 -32
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -39
- data/ext/pg.c +23 -50
- data/ext/pg.h +51 -81
- data/ext/pg_binary_decoder.c +73 -6
- data/ext/pg_coder.c +52 -3
- data/ext/pg_connection.c +369 -219
- data/ext/pg_copy_coder.c +10 -5
- data/ext/pg_result.c +343 -119
- data/ext/pg_text_decoder.c +597 -37
- data/ext/pg_text_encoder.c +6 -7
- data/ext/pg_tuple.c +541 -0
- data/ext/util.c +6 -6
- data/ext/util.h +2 -2
- data/lib/pg.rb +5 -7
- data/lib/pg/basic_type_mapping.rb +40 -7
- data/lib/pg/binary_decoder.rb +22 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +27 -3
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +1 -1
- data/lib/pg/text_decoder.rb +19 -23
- data/lib/pg/text_encoder.rb +35 -1
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +1 -1
- data/spec/helpers.rb +49 -21
- data/spec/pg/basic_type_mapping_spec.rb +230 -27
- data/spec/pg/connection_spec.rb +473 -277
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +48 -13
- data/spec/pg/tuple_spec.rb +280 -0
- data/spec/pg/type_map_by_class_spec.rb +1 -1
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_map_by_oid_spec.rb +1 -1
- 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 +184 -12
- data/spec/pg_spec.rb +2 -2
- metadata +37 -33
- metadata.gz.sig +0 -0
- data/lib/pg/deprecated_constants.rb +0 -21
data/ext/pg_binary_decoder.c
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
|
+
#include "ruby/version.h"
|
7
8
|
#include "pg.h"
|
8
9
|
#include "util.h"
|
9
10
|
#ifdef HAVE_INTTYPES_H
|
@@ -21,7 +22,7 @@ VALUE rb_mPG_BinaryDecoder;
|
|
21
22
|
*
|
22
23
|
*/
|
23
24
|
static VALUE
|
24
|
-
pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
25
|
+
pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
25
26
|
{
|
26
27
|
if (len < 1) {
|
27
28
|
rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
|
@@ -37,7 +38,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
37
38
|
*
|
38
39
|
*/
|
39
40
|
static VALUE
|
40
|
-
pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
41
|
+
pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
41
42
|
{
|
42
43
|
switch( len ){
|
43
44
|
case 2:
|
@@ -59,7 +60,7 @@ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
59
60
|
*
|
60
61
|
*/
|
61
62
|
static VALUE
|
62
|
-
pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
63
|
+
pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
63
64
|
{
|
64
65
|
union {
|
65
66
|
float f;
|
@@ -91,7 +92,7 @@ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
91
92
|
*
|
92
93
|
*/
|
93
94
|
VALUE
|
94
|
-
pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
95
|
+
pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
95
96
|
{
|
96
97
|
VALUE ret;
|
97
98
|
ret = rb_tainted_str_new( val, len );
|
@@ -106,7 +107,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
106
107
|
*
|
107
108
|
*/
|
108
109
|
static VALUE
|
109
|
-
pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
110
|
+
pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
110
111
|
{
|
111
112
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
112
113
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
|
@@ -130,6 +131,70 @@ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field,
|
|
130
131
|
return out_value;
|
131
132
|
}
|
132
133
|
|
134
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
135
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Document-class: PG::BinaryDecoder::Timestamp < PG::SimpleDecoder
|
139
|
+
*
|
140
|
+
* This is a decoder class for conversion of PostgreSQL binary timestamps
|
141
|
+
* to Ruby Time objects.
|
142
|
+
*
|
143
|
+
* The following flags can be used to specify timezone interpretation:
|
144
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Interpret timestamp as UTC time (default)
|
145
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Interpret timestamp as local time
|
146
|
+
* * +PG::Coder::TIMESTAMP_APP_UTC+ : Return timestamp as UTC time (default)
|
147
|
+
* * +PG::Coder::TIMESTAMP_APP_LOCAL+ : Return timestamp as local time
|
148
|
+
*
|
149
|
+
* Example:
|
150
|
+
* deco = PG::BinaryDecoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
|
151
|
+
* deco.decode("\0"*8) # => 2000-01-01 01:00:00 +0100
|
152
|
+
*/
|
153
|
+
static VALUE
|
154
|
+
pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
155
|
+
{
|
156
|
+
int64_t timestamp;
|
157
|
+
int64_t sec;
|
158
|
+
int64_t nsec;
|
159
|
+
VALUE t;
|
160
|
+
|
161
|
+
if( len != sizeof(timestamp) ){
|
162
|
+
rb_raise( rb_eTypeError, "wrong data for timestamp converter in tuple %d field %d length %d", tuple, field, len);
|
163
|
+
}
|
164
|
+
|
165
|
+
timestamp = read_nbo64(val);
|
166
|
+
|
167
|
+
switch(timestamp){
|
168
|
+
case PG_INT64_MAX:
|
169
|
+
return rb_str_new2("infinity");
|
170
|
+
case PG_INT64_MIN:
|
171
|
+
return rb_str_new2("-infinity");
|
172
|
+
default:
|
173
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
174
|
+
* Adjust the 30 years difference. */
|
175
|
+
sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
|
176
|
+
nsec = (timestamp % 1000000) * 1000;
|
177
|
+
|
178
|
+
#if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T) && defined(SIZEOF_TIME_T) && SIZEOF_TIME_T >= 8
|
179
|
+
/* Fast path for time conversion */
|
180
|
+
{
|
181
|
+
struct timespec ts = {sec, nsec};
|
182
|
+
t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
|
183
|
+
}
|
184
|
+
#else
|
185
|
+
t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(sec), LL2NUM(nsec / 1000));
|
186
|
+
if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
|
187
|
+
t = rb_funcall(t, rb_intern("utc"), 0);
|
188
|
+
}
|
189
|
+
#endif
|
190
|
+
if( conv->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
191
|
+
/* interpret it as local time */
|
192
|
+
t = rb_funcall(t, rb_intern("-"), 1, rb_funcall(t, rb_intern("utc_offset"), 0));
|
193
|
+
}
|
194
|
+
return t;
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
133
198
|
/*
|
134
199
|
* Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
|
135
200
|
*
|
@@ -156,6 +221,8 @@ init_pg_binary_decoder()
|
|
156
221
|
pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
157
222
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
|
158
223
|
pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
224
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
|
225
|
+
pg_define_coder( "Timestamp", pg_bin_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
159
226
|
|
160
227
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
|
161
228
|
pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
|
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,6 +57,7 @@ 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
|
|
@@ -192,7 +194,11 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
192
194
|
if( NIL_P(argv[0]) )
|
193
195
|
return Qnil;
|
194
196
|
|
195
|
-
|
197
|
+
if( this->format == 0 ){
|
198
|
+
val = StringValueCStr(argv[0]);
|
199
|
+
}else{
|
200
|
+
val = StringValuePtr(argv[0]);
|
201
|
+
}
|
196
202
|
if( !this->dec_func ){
|
197
203
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
198
204
|
}
|
@@ -265,6 +271,36 @@ pg_coder_format_get(VALUE self)
|
|
265
271
|
return INT2NUM(this->format);
|
266
272
|
}
|
267
273
|
|
274
|
+
/*
|
275
|
+
* call-seq:
|
276
|
+
* coder.flags = Integer
|
277
|
+
*
|
278
|
+
* Set coder specific bitwise OR-ed flags.
|
279
|
+
* See the particular en- or decoder description for available flags.
|
280
|
+
*
|
281
|
+
* The default is +0+.
|
282
|
+
*/
|
283
|
+
static VALUE
|
284
|
+
pg_coder_flags_set(VALUE self, VALUE flags)
|
285
|
+
{
|
286
|
+
t_pg_coder *this = DATA_PTR(self);
|
287
|
+
this->flags = NUM2INT(flags);
|
288
|
+
return flags;
|
289
|
+
}
|
290
|
+
|
291
|
+
/*
|
292
|
+
* call-seq:
|
293
|
+
* coder.flags -> Integer
|
294
|
+
*
|
295
|
+
* Get current bitwise OR-ed coder flags.
|
296
|
+
*/
|
297
|
+
static VALUE
|
298
|
+
pg_coder_flags_get(VALUE self)
|
299
|
+
{
|
300
|
+
t_pg_coder *this = DATA_PTR(self);
|
301
|
+
return INT2NUM(this->flags);
|
302
|
+
}
|
303
|
+
|
268
304
|
/*
|
269
305
|
* call-seq:
|
270
306
|
* coder.needs_quotation = Boolean
|
@@ -403,14 +439,14 @@ pg_coder_enc_func(t_pg_coder *this)
|
|
403
439
|
}
|
404
440
|
|
405
441
|
static VALUE
|
406
|
-
pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
442
|
+
pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
407
443
|
{
|
408
444
|
VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
|
409
445
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
410
446
|
}
|
411
447
|
|
412
448
|
static VALUE
|
413
|
-
pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
449
|
+
pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
414
450
|
{
|
415
451
|
VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
|
416
452
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
@@ -457,6 +493,19 @@ init_pg_coder()
|
|
457
493
|
rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
|
458
494
|
rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
|
459
495
|
rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
|
496
|
+
rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
|
497
|
+
rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
|
498
|
+
|
499
|
+
/* define flags to be used with PG::Coder#flags= */
|
500
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
|
501
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
|
502
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
|
503
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
|
504
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
|
505
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
|
506
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
|
507
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
|
508
|
+
|
460
509
|
/*
|
461
510
|
* Name of the coder or the corresponding data type.
|
462
511
|
*
|
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
|
|
@@ -18,19 +18,8 @@ static PQnoticeReceiver default_notice_receiver = NULL;
|
|
18
18
|
static PQnoticeProcessor default_notice_processor = NULL;
|
19
19
|
|
20
20
|
static VALUE pgconn_finish( VALUE );
|
21
|
-
#ifdef M17N_SUPPORTED
|
22
21
|
static VALUE pgconn_set_default_encoding( VALUE self );
|
23
22
|
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
|
34
23
|
|
35
24
|
/*
|
36
25
|
* Global functions
|
@@ -95,9 +84,8 @@ pgconn_close_socket_io( VALUE self )
|
|
95
84
|
VALUE socket_io = this->socket_io;
|
96
85
|
|
97
86
|
if ( RTEST(socket_io) ) {
|
98
|
-
#if defined(_WIN32)
|
99
|
-
|
100
|
-
if( rb_w32_unwrap_io_handle(ruby_sd) ){
|
87
|
+
#if defined(_WIN32)
|
88
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
|
101
89
|
rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
|
102
90
|
}
|
103
91
|
#endif
|
@@ -176,6 +164,10 @@ pgconn_gc_mark( t_pg_connection *this )
|
|
176
164
|
static void
|
177
165
|
pgconn_gc_free( t_pg_connection *this )
|
178
166
|
{
|
167
|
+
#if defined(_WIN32)
|
168
|
+
if ( RTEST(this->socket_io) )
|
169
|
+
rb_w32_unwrap_io_handle( this->ruby_sd );
|
170
|
+
#endif
|
179
171
|
if (this->pgconn != NULL)
|
180
172
|
PQfinish( this->pgconn );
|
181
173
|
|
@@ -209,6 +201,7 @@ pgconn_s_allocate( VALUE klass )
|
|
209
201
|
this->decoder_for_get_copy_data = Qnil;
|
210
202
|
this->trace_stream = Qnil;
|
211
203
|
this->external_encoding = Qnil;
|
204
|
+
this->guess_result_memsize = 1;
|
212
205
|
|
213
206
|
return self;
|
214
207
|
}
|
@@ -291,9 +284,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
291
284
|
rb_exc_raise(error);
|
292
285
|
}
|
293
286
|
|
294
|
-
#ifdef M17N_SUPPORTED
|
295
287
|
pgconn_set_default_encoding( self );
|
296
|
-
#endif
|
297
288
|
|
298
289
|
if (rb_block_given_p()) {
|
299
290
|
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
@@ -349,7 +340,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
349
340
|
return rb_conn;
|
350
341
|
}
|
351
342
|
|
352
|
-
#ifdef HAVE_PQPING
|
353
343
|
/*
|
354
344
|
* call-seq:
|
355
345
|
* PG::Connection.ping(connection_hash) -> Integer
|
@@ -367,6 +357,8 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
367
357
|
* could not establish connection
|
368
358
|
* [+PQPING_NO_ATTEMPT+]
|
369
359
|
* connection not attempted (bad params)
|
360
|
+
*
|
361
|
+
* Available since PostgreSQL-9.1
|
370
362
|
*/
|
371
363
|
static VALUE
|
372
364
|
pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
@@ -379,7 +371,6 @@ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
|
|
379
371
|
|
380
372
|
return INT2FIX((int)ping);
|
381
373
|
}
|
382
|
-
#endif
|
383
374
|
|
384
375
|
|
385
376
|
/*
|
@@ -418,16 +409,65 @@ pgconn_s_conndefaults(VALUE self)
|
|
418
409
|
}
|
419
410
|
|
420
411
|
|
412
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
421
413
|
/*
|
422
414
|
* call-seq:
|
423
|
-
*
|
415
|
+
* conn.encrypt_password( password, username, algorithm=nil ) -> String
|
416
|
+
*
|
417
|
+
* This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
|
418
|
+
* 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.
|
419
|
+
* Instead, use this function to convert the password to encrypted form before it is sent.
|
424
420
|
*
|
425
|
-
*
|
426
|
-
*
|
427
|
-
*
|
428
|
-
*
|
421
|
+
* The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
|
422
|
+
* +algorithm+ specifies the encryption algorithm to use to encrypt the password.
|
423
|
+
* 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).
|
424
|
+
* Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
|
425
|
+
* If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
|
426
|
+
* That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
|
427
|
+
* 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.
|
429
428
|
*
|
430
429
|
* Return value is the encrypted password.
|
430
|
+
* The caller can assume the string doesn't contain any special characters that would require escaping.
|
431
|
+
*
|
432
|
+
* Available since PostgreSQL-10
|
433
|
+
*/
|
434
|
+
static VALUE
|
435
|
+
pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
|
436
|
+
{
|
437
|
+
char *encrypted = NULL;
|
438
|
+
VALUE rval = Qnil;
|
439
|
+
VALUE password, username, algorithm;
|
440
|
+
PGconn *conn = pg_get_pgconn(self);
|
441
|
+
|
442
|
+
rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
|
443
|
+
|
444
|
+
Check_Type(password, T_STRING);
|
445
|
+
Check_Type(username, T_STRING);
|
446
|
+
|
447
|
+
encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
|
448
|
+
if ( encrypted ) {
|
449
|
+
rval = rb_str_new2( encrypted );
|
450
|
+
PQfreemem( encrypted );
|
451
|
+
|
452
|
+
OBJ_INFECT( rval, password );
|
453
|
+
OBJ_INFECT( rval, username );
|
454
|
+
OBJ_INFECT( rval, algorithm );
|
455
|
+
} else {
|
456
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
457
|
+
}
|
458
|
+
|
459
|
+
return rval;
|
460
|
+
}
|
461
|
+
#endif
|
462
|
+
|
463
|
+
|
464
|
+
/*
|
465
|
+
* call-seq:
|
466
|
+
* PG::Connection.encrypt_password( password, username ) -> String
|
467
|
+
*
|
468
|
+
* This is an older, deprecated version of #encrypt_password.
|
469
|
+
* The difference is that this function always uses +md5+ as the encryption algorithm.
|
470
|
+
*
|
431
471
|
*/
|
432
472
|
static VALUE
|
433
473
|
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
@@ -613,7 +653,7 @@ pgconn_user(VALUE self)
|
|
613
653
|
* call-seq:
|
614
654
|
* conn.pass()
|
615
655
|
*
|
616
|
-
* Returns the authenticated
|
656
|
+
* Returns the authenticated password.
|
617
657
|
*/
|
618
658
|
static VALUE
|
619
659
|
pgconn_pass(VALUE self)
|
@@ -686,6 +726,7 @@ pgconn_options(VALUE self)
|
|
686
726
|
*
|
687
727
|
* Returns the connection options used by a live connection.
|
688
728
|
*
|
729
|
+
* Available since PostgreSQL-9.3
|
689
730
|
*/
|
690
731
|
static VALUE
|
691
732
|
pgconn_conninfo( VALUE self )
|
@@ -807,6 +848,8 @@ pgconn_error_message(VALUE self)
|
|
807
848
|
* call-seq:
|
808
849
|
* conn.socket() -> Integer
|
809
850
|
*
|
851
|
+
* This method is deprecated. Please use the more portable method #socket_io .
|
852
|
+
*
|
810
853
|
* Returns the socket's file descriptor for this connection.
|
811
854
|
* <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
|
812
855
|
* If you do so, you will likely also want to set <tt>autoclose=false</tt>
|
@@ -815,7 +858,7 @@ pgconn_error_message(VALUE self)
|
|
815
858
|
* creates an IO that's associated with the connection object itself,
|
816
859
|
* and so won't go out of scope until the connection does.
|
817
860
|
*
|
818
|
-
* *Note:* On Windows the file descriptor is not
|
861
|
+
* *Note:* On Windows the file descriptor is not usable,
|
819
862
|
* since it can not be used to build a Ruby IO object.
|
820
863
|
*/
|
821
864
|
static VALUE
|
@@ -827,22 +870,17 @@ pgconn_socket(VALUE self)
|
|
827
870
|
return INT2NUM(sd);
|
828
871
|
}
|
829
872
|
|
830
|
-
|
831
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
832
|
-
|
833
873
|
/*
|
834
874
|
* call-seq:
|
835
875
|
* conn.socket_io() -> IO
|
836
876
|
*
|
837
|
-
* Fetch a
|
877
|
+
* Fetch a memorized IO object created from the Connection's underlying socket.
|
838
878
|
* This object can be used for IO.select to wait for events while running
|
839
879
|
* asynchronous API calls.
|
840
880
|
*
|
841
881
|
* Using this instead of #socket avoids the problem of the underlying connection
|
842
882
|
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
843
|
-
* goes out of scope.
|
844
|
-
*
|
845
|
-
* This method can also be used on Windows but requires Ruby-2.0+.
|
883
|
+
* goes out of scope. In contrast to #socket, it also works on Windows.
|
846
884
|
*/
|
847
885
|
static VALUE
|
848
886
|
pgconn_socket_io(VALUE self)
|
@@ -859,16 +897,15 @@ pgconn_socket_io(VALUE self)
|
|
859
897
|
|
860
898
|
#ifdef _WIN32
|
861
899
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
900
|
+
this->ruby_sd = ruby_sd;
|
862
901
|
#else
|
863
902
|
ruby_sd = sd;
|
864
903
|
#endif
|
865
904
|
|
866
905
|
socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
|
867
906
|
|
868
|
-
/* Disable autoclose feature
|
869
|
-
|
870
|
-
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
871
|
-
}
|
907
|
+
/* Disable autoclose feature */
|
908
|
+
rb_funcall( socket_io, id_autoclose, 1, Qfalse );
|
872
909
|
|
873
910
|
this->socket_io = socket_io;
|
874
911
|
}
|
@@ -876,8 +913,6 @@ pgconn_socket_io(VALUE self)
|
|
876
913
|
return socket_io;
|
877
914
|
}
|
878
915
|
|
879
|
-
#endif
|
880
|
-
|
881
916
|
/*
|
882
917
|
* call-seq:
|
883
918
|
* conn.backend_pid() -> Integer
|
@@ -930,7 +965,7 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
930
965
|
* conn.exec(sql) {|pg_result| block }
|
931
966
|
*
|
932
967
|
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
933
|
-
*
|
968
|
+
* On success, it returns a PG::Result instance with all result rows and columns.
|
934
969
|
* On failure, it raises a PG::Error.
|
935
970
|
*
|
936
971
|
* For backward compatibility, if you pass more than one parameter to this method,
|
@@ -941,9 +976,9 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
|
|
941
976
|
* and the PG::Result object will automatically be cleared when the block terminates.
|
942
977
|
* In this instance, <code>conn.exec</code> returns the value of the block.
|
943
978
|
*
|
944
|
-
* #
|
979
|
+
* #sync_exec is implemented on the synchronous command processing API of libpq, whereas
|
945
980
|
* #async_exec is implemented on the asynchronous API.
|
946
|
-
* #
|
981
|
+
* #sync_exec is somewhat faster that #async_exec, but blocks any signals to be processed until
|
947
982
|
* the query is finished. This is most notably visible by a delayed reaction to Control+C.
|
948
983
|
* Both methods ensure that other threads can process while waiting for the server to
|
949
984
|
* complete the request.
|
@@ -955,8 +990,8 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
955
990
|
PGresult *result = NULL;
|
956
991
|
VALUE rb_pgresult;
|
957
992
|
|
958
|
-
/* If called with no parameters, use PQexec */
|
959
|
-
if ( argc == 1 ) {
|
993
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
994
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
960
995
|
VALUE query_str = argv[0];
|
961
996
|
|
962
997
|
result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
|
@@ -967,11 +1002,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
|
|
967
1002
|
}
|
968
1003
|
return rb_pgresult;
|
969
1004
|
}
|
1005
|
+
pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
|
970
1006
|
|
971
1007
|
/* Otherwise, just call #exec_params instead for backward-compatibility */
|
972
|
-
|
973
|
-
return pgconn_exec_params( argc, argv, self );
|
974
|
-
}
|
1008
|
+
return pgconn_exec_params( argc, argv, self );
|
975
1009
|
|
976
1010
|
}
|
977
1011
|
|
@@ -1254,7 +1288,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
|
|
1254
1288
|
* for binary.
|
1255
1289
|
*
|
1256
1290
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1257
|
-
* This will type cast the params
|
1291
|
+
* This will type cast the params from various Ruby types before transmission
|
1258
1292
|
* based on the encoders defined by the type map. When a type encoder is used
|
1259
1293
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1260
1294
|
* instead out of the hash form described above.
|
@@ -1274,14 +1308,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
|
|
1274
1308
|
int resultFormat;
|
1275
1309
|
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1276
1310
|
|
1311
|
+
/* For compatibility we accept 1 to 4 parameters */
|
1277
1312
|
rb_scan_args(argc, argv, "13", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1278
1313
|
paramsData.with_types = 1;
|
1279
1314
|
|
1280
1315
|
/*
|
1281
|
-
*
|
1282
|
-
*
|
1316
|
+
* For backward compatibility no or +nil+ for the second parameter
|
1317
|
+
* is passed to #exec
|
1283
1318
|
*/
|
1284
1319
|
if ( NIL_P(paramsData.params) ) {
|
1320
|
+
pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
|
1285
1321
|
return pgconn_exec( 1, argv, self );
|
1286
1322
|
}
|
1287
1323
|
pgconn_query_assign_typemap( self, ¶msData );
|
@@ -1390,7 +1426,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
|
1390
1426
|
* for binary.
|
1391
1427
|
*
|
1392
1428
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1393
|
-
* This will type cast the params
|
1429
|
+
* This will type cast the params from various Ruby types before transmission
|
1394
1430
|
* based on the encoders defined by the type map. When a type encoder is used
|
1395
1431
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1396
1432
|
* instead out of the hash form described above.
|
@@ -1547,7 +1583,7 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1547
1583
|
int enc_idx;
|
1548
1584
|
int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
|
1549
1585
|
|
1550
|
-
|
1586
|
+
StringValueCStr(string);
|
1551
1587
|
enc_idx = ENCODING_GET( singleton ? string : self );
|
1552
1588
|
if( ENCODING_GET(string) != enc_idx ){
|
1553
1589
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
@@ -1646,12 +1682,13 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
|
1646
1682
|
return ret;
|
1647
1683
|
}
|
1648
1684
|
|
1649
|
-
#ifdef HAVE_PQESCAPELITERAL
|
1650
1685
|
/*
|
1651
1686
|
* call-seq:
|
1652
1687
|
* conn.escape_literal( str ) -> String
|
1653
1688
|
*
|
1654
1689
|
* Escape an arbitrary String +str+ as a literal.
|
1690
|
+
*
|
1691
|
+
* Available since PostgreSQL-9.0
|
1655
1692
|
*/
|
1656
1693
|
static VALUE
|
1657
1694
|
pgconn_escape_literal(VALUE self, VALUE string)
|
@@ -1662,7 +1699,7 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1662
1699
|
VALUE result = Qnil;
|
1663
1700
|
int enc_idx = ENCODING_GET(self);
|
1664
1701
|
|
1665
|
-
|
1702
|
+
StringValueCStr(string);
|
1666
1703
|
if( ENCODING_GET(string) != enc_idx ){
|
1667
1704
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1668
1705
|
}
|
@@ -1682,9 +1719,7 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1682
1719
|
|
1683
1720
|
return result;
|
1684
1721
|
}
|
1685
|
-
#endif
|
1686
1722
|
|
1687
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
1688
1723
|
/*
|
1689
1724
|
* call-seq:
|
1690
1725
|
* conn.escape_identifier( str ) -> String
|
@@ -1694,6 +1729,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1694
1729
|
* This method does the same as #quote_ident with a String argument,
|
1695
1730
|
* but it doesn't support an Array argument and it makes use of libpq
|
1696
1731
|
* to process the string.
|
1732
|
+
*
|
1733
|
+
* Available since PostgreSQL-9.0
|
1697
1734
|
*/
|
1698
1735
|
static VALUE
|
1699
1736
|
pgconn_escape_identifier(VALUE self, VALUE string)
|
@@ -1704,7 +1741,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1704
1741
|
VALUE result = Qnil;
|
1705
1742
|
int enc_idx = ENCODING_GET(self);
|
1706
1743
|
|
1707
|
-
|
1744
|
+
StringValueCStr(string);
|
1708
1745
|
if( ENCODING_GET(string) != enc_idx ){
|
1709
1746
|
string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
|
1710
1747
|
}
|
@@ -1724,9 +1761,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1724
1761
|
|
1725
1762
|
return result;
|
1726
1763
|
}
|
1727
|
-
#endif
|
1728
1764
|
|
1729
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
1730
1765
|
/*
|
1731
1766
|
* call-seq:
|
1732
1767
|
* conn.set_single_row_mode -> self
|
@@ -1763,6 +1798,7 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1763
1798
|
* end
|
1764
1799
|
* end
|
1765
1800
|
*
|
1801
|
+
* Available since PostgreSQL-9.2
|
1766
1802
|
*/
|
1767
1803
|
static VALUE
|
1768
1804
|
pgconn_set_single_row_mode(VALUE self)
|
@@ -1779,17 +1815,55 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1779
1815
|
|
1780
1816
|
return self;
|
1781
1817
|
}
|
1782
|
-
|
1818
|
+
|
1819
|
+
static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
|
1783
1820
|
|
1784
1821
|
/*
|
1785
1822
|
* call-seq:
|
1786
|
-
* conn.send_query(sql
|
1823
|
+
* conn.send_query(sql) -> nil
|
1787
1824
|
*
|
1788
1825
|
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1789
1826
|
* asynchronous processing, and immediately returns.
|
1790
1827
|
* On failure, it raises a PG::Error.
|
1791
1828
|
*
|
1792
|
-
*
|
1829
|
+
* For backward compatibility, if you pass more than one parameter to this method,
|
1830
|
+
* it will call #send_query_params for you. New code should explicitly use #send_query_params if
|
1831
|
+
* argument placeholders are used.
|
1832
|
+
*
|
1833
|
+
*/
|
1834
|
+
static VALUE
|
1835
|
+
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1836
|
+
{
|
1837
|
+
PGconn *conn = pg_get_pgconn(self);
|
1838
|
+
VALUE error;
|
1839
|
+
|
1840
|
+
/* If called with no or nil parameters, use PQexec for compatibility */
|
1841
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1842
|
+
if(gvl_PQsendQuery(conn, pg_cstr_enc(argv[0], ENCODING_GET(self))) == 0) {
|
1843
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1844
|
+
rb_iv_set(error, "@connection", self);
|
1845
|
+
rb_exc_raise(error);
|
1846
|
+
}
|
1847
|
+
return Qnil;
|
1848
|
+
}
|
1849
|
+
|
1850
|
+
pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
|
1851
|
+
|
1852
|
+
/* If called with parameters, and optionally result_format,
|
1853
|
+
* use PQsendQueryParams
|
1854
|
+
*/
|
1855
|
+
return pgconn_send_query_params( argc, argv, self);
|
1856
|
+
}
|
1857
|
+
|
1858
|
+
/*
|
1859
|
+
* call-seq:
|
1860
|
+
* conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
|
1861
|
+
*
|
1862
|
+
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1863
|
+
* asynchronous processing, and immediately returns.
|
1864
|
+
* On failure, it raises a PG::Error.
|
1865
|
+
*
|
1866
|
+
* +params+ is an array of the bind parameters for the SQL query.
|
1793
1867
|
* Each element of the +params+ array may be either:
|
1794
1868
|
* a hash of the form:
|
1795
1869
|
* {:value => String (value of bind parameter)
|
@@ -1813,14 +1887,14 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1813
1887
|
* for binary.
|
1814
1888
|
*
|
1815
1889
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1816
|
-
* This will type cast the params
|
1890
|
+
* This will type cast the params from various Ruby types before transmission
|
1817
1891
|
* based on the encoders defined by the type map. When a type encoder is used
|
1818
1892
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1819
1893
|
* instead out of the hash form described above.
|
1820
1894
|
*
|
1821
1895
|
*/
|
1822
1896
|
static VALUE
|
1823
|
-
|
1897
|
+
pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
1824
1898
|
{
|
1825
1899
|
PGconn *conn = pg_get_pgconn(self);
|
1826
1900
|
int result;
|
@@ -1830,23 +1904,9 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1830
1904
|
int resultFormat;
|
1831
1905
|
struct query_params_data paramsData = { ENCODING_GET(self) };
|
1832
1906
|
|
1833
|
-
rb_scan_args(argc, argv, "
|
1907
|
+
rb_scan_args(argc, argv, "22", &command, ¶msData.params, &in_res_fmt, ¶msData.typemap);
|
1834
1908
|
paramsData.with_types = 1;
|
1835
1909
|
|
1836
|
-
/* If called with no parameters, use PQsendQuery */
|
1837
|
-
if(NIL_P(paramsData.params)) {
|
1838
|
-
if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
|
1839
|
-
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1840
|
-
rb_iv_set(error, "@connection", self);
|
1841
|
-
rb_exc_raise(error);
|
1842
|
-
}
|
1843
|
-
return Qnil;
|
1844
|
-
}
|
1845
|
-
|
1846
|
-
/* If called with parameters, and optionally result_format,
|
1847
|
-
* use PQsendQueryParams
|
1848
|
-
*/
|
1849
|
-
|
1850
1910
|
pgconn_query_assign_typemap( self, ¶msData );
|
1851
1911
|
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
|
1852
1912
|
nParams = alloc_query_params( ¶msData );
|
@@ -1953,7 +2013,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1953
2013
|
* for binary.
|
1954
2014
|
*
|
1955
2015
|
* type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
|
1956
|
-
* This will type cast the params
|
2016
|
+
* This will type cast the params from various Ruby types before transmission
|
1957
2017
|
* based on the encoders defined by the type map. When a type encoder is used
|
1958
2018
|
* the format and oid of a given bind parameter are retrieved from the encoder
|
1959
2019
|
* instead out of the hash form described above.
|
@@ -2203,7 +2263,6 @@ pgconn_flush(self)
|
|
2203
2263
|
static VALUE
|
2204
2264
|
pgconn_cancel(VALUE self)
|
2205
2265
|
{
|
2206
|
-
#ifdef HAVE_PQGETCANCEL
|
2207
2266
|
char errbuf[256];
|
2208
2267
|
PGcancel *cancel;
|
2209
2268
|
VALUE retval;
|
@@ -2221,9 +2280,6 @@ pgconn_cancel(VALUE self)
|
|
2221
2280
|
|
2222
2281
|
PQfreeCancel(cancel);
|
2223
2282
|
return retval;
|
2224
|
-
#else
|
2225
|
-
rb_notimplement();
|
2226
|
-
#endif
|
2227
2283
|
}
|
2228
2284
|
|
2229
2285
|
|
@@ -2267,56 +2323,15 @@ pgconn_notifies(VALUE self)
|
|
2267
2323
|
return hash;
|
2268
2324
|
}
|
2269
2325
|
|
2270
|
-
/* Win32 + Ruby 1.8 */
|
2271
|
-
#if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
|
2272
|
-
|
2273
|
-
/*
|
2274
|
-
* Duplicate the sockets from libpq and create temporary CRT FDs
|
2275
|
-
*/
|
2276
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2277
|
-
{
|
2278
|
-
int i;
|
2279
|
-
crt_set->fd_count = os_set->fd_count;
|
2280
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2281
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2282
|
-
/* dupicate the SOCKET */
|
2283
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2284
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2285
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2286
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2287
|
-
os_set->fd_array[i] = s;
|
2288
|
-
crt_set->fd_array[i] = fd;
|
2289
|
-
}
|
2290
|
-
}
|
2291
|
-
|
2292
|
-
/*
|
2293
|
-
* Clean up the CRT FDs from create_crt_fd()
|
2294
|
-
*/
|
2295
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2296
|
-
{
|
2297
|
-
int i;
|
2298
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2299
|
-
/* cleanup the CRT fd */
|
2300
|
-
_close(crt_set->fd_array[i]);
|
2301
|
-
/* cleanup the duplicated SOCKET */
|
2302
|
-
closesocket(os_set->fd_array[i]);
|
2303
|
-
}
|
2304
|
-
}
|
2305
|
-
#endif
|
2306
|
-
|
2307
2326
|
/* Win32 + Ruby 1.9+ */
|
2308
|
-
#if defined(
|
2327
|
+
#if defined( _WIN32 )
|
2309
2328
|
/*
|
2310
2329
|
* On Windows, use platform-specific strategies to wait for the socket
|
2311
|
-
* instead of
|
2330
|
+
* instead of rb_wait_for_single_fd().
|
2312
2331
|
*/
|
2313
2332
|
|
2314
2333
|
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2315
2334
|
|
2316
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2317
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2318
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2319
|
-
|
2320
2335
|
static void *
|
2321
2336
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
|
2322
2337
|
{
|
@@ -2393,7 +2408,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2393
2408
|
|
2394
2409
|
#else
|
2395
2410
|
|
2396
|
-
/* non Win32
|
2411
|
+
/* non Win32 */
|
2397
2412
|
|
2398
2413
|
static void *
|
2399
2414
|
wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
@@ -2401,11 +2416,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2401
2416
|
int sd = PQsocket( conn );
|
2402
2417
|
int ret;
|
2403
2418
|
void *retval;
|
2404
|
-
rb_fdset_t sd_rset;
|
2405
2419
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2406
|
-
#ifdef _WIN32
|
2407
|
-
rb_fdset_t crt_sd_rset;
|
2408
|
-
#endif
|
2409
2420
|
|
2410
2421
|
if ( sd < 0 )
|
2411
2422
|
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
@@ -2414,25 +2425,12 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2414
2425
|
if ( PQconsumeInput(conn) == 0 )
|
2415
2426
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2416
2427
|
|
2417
|
-
rb_fd_init( &sd_rset );
|
2418
|
-
|
2419
2428
|
if ( ptimeout ) {
|
2420
2429
|
gettimeofday(&currtime, NULL);
|
2421
2430
|
timeradd(&currtime, ptimeout, &aborttime);
|
2422
2431
|
}
|
2423
2432
|
|
2424
2433
|
while ( !(retval=is_readable(conn)) ) {
|
2425
|
-
rb_fd_zero( &sd_rset );
|
2426
|
-
rb_fd_set( sd, &sd_rset );
|
2427
|
-
|
2428
|
-
#ifdef _WIN32
|
2429
|
-
/* Ruby's FD_SET is modified on win32 to convert a file descriptor
|
2430
|
-
* to osfhandle, but we already get a osfhandle from PQsocket().
|
2431
|
-
* Therefore it's overwritten here. */
|
2432
|
-
sd_rset.fd_array[0] = sd;
|
2433
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2434
|
-
#endif
|
2435
|
-
|
2436
2434
|
if ( ptimeout ) {
|
2437
2435
|
gettimeofday(&currtime, NULL);
|
2438
2436
|
timersub(&aborttime, &currtime, &waittime);
|
@@ -2441,35 +2439,26 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2441
2439
|
/* Is the given timeout valid? */
|
2442
2440
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2443
2441
|
/* Wait for the socket to become readable before checking again */
|
2444
|
-
ret =
|
2442
|
+
ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
|
2445
2443
|
} else {
|
2446
2444
|
ret = 0;
|
2447
2445
|
}
|
2448
2446
|
|
2449
|
-
|
2450
|
-
#ifdef _WIN32
|
2451
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2452
|
-
#endif
|
2453
|
-
|
2454
2447
|
if ( ret < 0 ){
|
2455
|
-
|
2456
|
-
rb_sys_fail( "rb_thread_select()" );
|
2448
|
+
rb_sys_fail( "rb_wait_for_single_fd()" );
|
2457
2449
|
}
|
2458
2450
|
|
2459
2451
|
/* Return false if the select() timed out */
|
2460
2452
|
if ( ret == 0 ){
|
2461
|
-
rb_fd_term( &sd_rset );
|
2462
2453
|
return NULL;
|
2463
2454
|
}
|
2464
2455
|
|
2465
2456
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2466
2457
|
if ( PQconsumeInput(conn) == 0 ){
|
2467
|
-
rb_fd_term( &sd_rset );
|
2468
2458
|
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2469
2459
|
}
|
2470
2460
|
}
|
2471
2461
|
|
2472
|
-
rb_fd_term( &sd_rset );
|
2473
2462
|
return retval;
|
2474
2463
|
}
|
2475
2464
|
|
@@ -2484,22 +2473,15 @@ notify_readable(PGconn *conn)
|
|
2484
2473
|
|
2485
2474
|
/*
|
2486
2475
|
* call-seq:
|
2487
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2488
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2489
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2476
|
+
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
|
2490
2477
|
*
|
2491
2478
|
* Blocks while waiting for notification(s), or until the optional
|
2492
2479
|
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2493
2480
|
* measured in seconds and can be fractional.
|
2494
2481
|
*
|
2495
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2496
|
-
*
|
2497
|
-
*
|
2498
|
-
*
|
2499
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2500
|
-
* the optional +payload+ string, it will be given to the block as the
|
2501
|
-
* third argument.
|
2502
|
-
*
|
2482
|
+
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
|
2483
|
+
* If used in block form, passes the name of the NOTIFY +event+, the generating
|
2484
|
+
* +pid+ and the optional +payload+ string into the block.
|
2503
2485
|
*/
|
2504
2486
|
static VALUE
|
2505
2487
|
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
@@ -2528,12 +2510,10 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2528
2510
|
relname = rb_tainted_str_new2( pnotification->relname );
|
2529
2511
|
PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
|
2530
2512
|
be_pid = INT2NUM( pnotification->be_pid );
|
2531
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2532
2513
|
if ( *pnotification->extra ) {
|
2533
2514
|
extra = rb_tainted_str_new2( pnotification->extra );
|
2534
2515
|
PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
|
2535
2516
|
}
|
2536
|
-
#endif
|
2537
2517
|
PQfreemem( pnotification );
|
2538
2518
|
|
2539
2519
|
if ( rb_block_given_p() )
|
@@ -2552,9 +2532,10 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2552
2532
|
* not sent (false is only possible if the connection
|
2553
2533
|
* is in nonblocking mode, and this command would block).
|
2554
2534
|
*
|
2555
|
-
*
|
2556
|
-
* This encodes the
|
2557
|
-
*
|
2535
|
+
* _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
|
2536
|
+
* This encodes the data fields given as _buffer_ from an Array of Strings to
|
2537
|
+
* PostgreSQL's COPY text format inclusive proper escaping. Optionally
|
2538
|
+
* the encoder can type cast the fields from various Ruby types in one step,
|
2558
2539
|
* if PG::TextEncoder::CopyRow#type_map is set accordingly.
|
2559
2540
|
*
|
2560
2541
|
* Raises an exception if an error occurs.
|
@@ -2659,15 +2640,18 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2659
2640
|
|
2660
2641
|
/*
|
2661
2642
|
* call-seq:
|
2662
|
-
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) ->
|
2643
|
+
* conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
|
2663
2644
|
*
|
2664
|
-
* Return
|
2645
|
+
* Return one row of data, +nil+
|
2665
2646
|
* if the copy is done, or +false+ if the call would
|
2666
2647
|
* block (only possible if _async_ is true).
|
2667
2648
|
*
|
2668
|
-
*
|
2669
|
-
*
|
2670
|
-
*
|
2649
|
+
* If _decoder_ is not set or +nil+, data is returned as binary string.
|
2650
|
+
*
|
2651
|
+
* If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
|
2652
|
+
* PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
|
2653
|
+
* COPY text format to an Array of Strings.
|
2654
|
+
* Optionally the decoder can type cast the single fields to various Ruby types in one step,
|
2671
2655
|
* if PG::TextDecoder::CopyRow#type_map is set accordingly.
|
2672
2656
|
*
|
2673
2657
|
* See also #copy_data.
|
@@ -2968,11 +2952,9 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2968
2952
|
Check_Type(str, T_STRING);
|
2969
2953
|
|
2970
2954
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
|
2971
|
-
rb_raise(rb_ePGerror, "
|
2955
|
+
rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
|
2972
2956
|
}
|
2973
|
-
#ifdef M17N_SUPPORTED
|
2974
2957
|
pgconn_set_internal_encoding_index( self );
|
2975
|
-
#endif
|
2976
2958
|
|
2977
2959
|
return Qnil;
|
2978
2960
|
}
|
@@ -3100,10 +3082,6 @@ static VALUE
|
|
3100
3082
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
3101
3083
|
PGconn *conn = pg_get_pgconn( self );
|
3102
3084
|
|
3103
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
3104
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
3105
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
3106
|
-
|
3107
3085
|
struct timeval timeout;
|
3108
3086
|
struct timeval *ptimeout = NULL;
|
3109
3087
|
VALUE timeout_in;
|
@@ -3170,24 +3148,89 @@ pgconn_get_last_result(VALUE self)
|
|
3170
3148
|
|
3171
3149
|
/*
|
3172
3150
|
* call-seq:
|
3173
|
-
* conn.
|
3174
|
-
* conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
|
3151
|
+
* conn.discard_results()
|
3175
3152
|
*
|
3176
|
-
*
|
3153
|
+
* Silently discard any prior query result that application didn't eat.
|
3154
|
+
* This is done prior of Connection#exec and sibling methods and can
|
3155
|
+
* be called explicitly when using the async API.
|
3156
|
+
*/
|
3157
|
+
static VALUE
|
3158
|
+
pgconn_discard_results(VALUE self)
|
3159
|
+
{
|
3160
|
+
PGconn *conn = pg_get_pgconn(self);
|
3161
|
+
|
3162
|
+
PGresult *cur;
|
3163
|
+
while ((cur = gvl_PQgetResult(conn)) != NULL) {
|
3164
|
+
int status = PQresultStatus(cur);
|
3165
|
+
PQclear(cur);
|
3166
|
+
if (status == PGRES_COPY_IN){
|
3167
|
+
gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
|
3168
|
+
}
|
3169
|
+
if (status == PGRES_COPY_OUT){
|
3170
|
+
char *buffer = NULL;
|
3171
|
+
while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
|
3172
|
+
PQfreemem(buffer);
|
3173
|
+
}
|
3174
|
+
}
|
3175
|
+
|
3176
|
+
return Qnil;
|
3177
|
+
}
|
3178
|
+
|
3179
|
+
/*
|
3180
|
+
* call-seq:
|
3181
|
+
* conn.async_exec(sql) -> PG::Result
|
3182
|
+
* conn.async_exec(sql) {|pg_result| block }
|
3183
|
+
*
|
3184
|
+
* This function has the same behavior as #sync_exec,
|
3177
3185
|
* but is implemented using the asynchronous command
|
3178
3186
|
* processing API of libpq.
|
3187
|
+
*
|
3188
|
+
* Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
|
3189
|
+
* However #async_exec has two advantages:
|
3190
|
+
*
|
3191
|
+
* 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
|
3192
|
+
* 2. Ruby VM gets notified about IO blocked operations.
|
3193
|
+
* It can therefore schedule thing like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
|
3179
3194
|
*/
|
3180
3195
|
static VALUE
|
3181
3196
|
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
3182
3197
|
{
|
3183
3198
|
VALUE rb_pgresult = Qnil;
|
3184
3199
|
|
3185
|
-
|
3200
|
+
pgconn_discard_results( self );
|
3201
|
+
pgconn_send_query( argc, argv, self );
|
3186
3202
|
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3187
|
-
pgconn_get_last_result( self );
|
3203
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3188
3204
|
|
3189
|
-
|
3190
|
-
|
3205
|
+
if ( rb_block_given_p() ) {
|
3206
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3207
|
+
}
|
3208
|
+
return rb_pgresult;
|
3209
|
+
}
|
3210
|
+
|
3211
|
+
|
3212
|
+
/*
|
3213
|
+
* call-seq:
|
3214
|
+
* conn.async_exec_params(sql, params [, result_format [, type_map ]] ) -> nil
|
3215
|
+
* conn.async_exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
|
3216
|
+
*
|
3217
|
+
* This function has the same behavior as #sync_exec_params, but is implemented using the asynchronous command processing API of libpq.
|
3218
|
+
* See #async_exec for the differences between the two API variants.
|
3219
|
+
*/
|
3220
|
+
static VALUE
|
3221
|
+
pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
|
3222
|
+
{
|
3223
|
+
VALUE rb_pgresult = Qnil;
|
3224
|
+
|
3225
|
+
pgconn_discard_results( self );
|
3226
|
+
/* If called with no or nil parameters, use PQsendQuery for compatibility */
|
3227
|
+
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
3228
|
+
pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
|
3229
|
+
pgconn_send_query( argc, argv, self );
|
3230
|
+
} else {
|
3231
|
+
pgconn_send_query_params( argc, argv, self );
|
3232
|
+
}
|
3233
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3191
3234
|
rb_pgresult = pgconn_get_last_result( self );
|
3192
3235
|
|
3193
3236
|
if ( rb_block_given_p() ) {
|
@@ -3197,15 +3240,111 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
|
3197
3240
|
}
|
3198
3241
|
|
3199
3242
|
|
3200
|
-
|
3201
|
-
|
3243
|
+
/*
|
3244
|
+
* call-seq:
|
3245
|
+
* conn.async_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
|
3246
|
+
*
|
3247
|
+
* This function has the same behavior as #sync_prepare, but is implemented using the asynchronous command processing API of libpq.
|
3248
|
+
* See #async_exec for the differences between the two API variants.
|
3249
|
+
*/
|
3250
|
+
static VALUE
|
3251
|
+
pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
|
3252
|
+
{
|
3253
|
+
VALUE rb_pgresult = Qnil;
|
3254
|
+
|
3255
|
+
pgconn_discard_results( self );
|
3256
|
+
pgconn_send_prepare( argc, argv, self );
|
3257
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3258
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3259
|
+
|
3260
|
+
if ( rb_block_given_p() ) {
|
3261
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3262
|
+
}
|
3263
|
+
return rb_pgresult;
|
3264
|
+
}
|
3265
|
+
|
3266
|
+
|
3267
|
+
/*
|
3268
|
+
* call-seq:
|
3269
|
+
* conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
|
3270
|
+
* conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
|
3271
|
+
*
|
3272
|
+
* This function has the same behavior as #sync_exec_prepared, but is implemented using the asynchronous command processing API of libpq.
|
3273
|
+
* See #async_exec for the differences between the two API variants.
|
3274
|
+
*/
|
3275
|
+
static VALUE
|
3276
|
+
pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
|
3277
|
+
{
|
3278
|
+
VALUE rb_pgresult = Qnil;
|
3279
|
+
|
3280
|
+
pgconn_discard_results( self );
|
3281
|
+
pgconn_send_query_prepared( argc, argv, self );
|
3282
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3283
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3202
3284
|
|
3285
|
+
if ( rb_block_given_p() ) {
|
3286
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3287
|
+
}
|
3288
|
+
return rb_pgresult;
|
3289
|
+
}
|
3290
|
+
|
3291
|
+
|
3292
|
+
/*
|
3293
|
+
* call-seq:
|
3294
|
+
* conn.async_describe_portal( portal_name ) -> PG::Result
|
3295
|
+
*
|
3296
|
+
* This function has the same behavior as #sync_describe_portal, but is implemented using the asynchronous command processing API of libpq.
|
3297
|
+
* See #async_exec for the differences between the two API variants.
|
3298
|
+
*/
|
3299
|
+
static VALUE
|
3300
|
+
pgconn_async_describe_portal(VALUE self, VALUE portal)
|
3301
|
+
{
|
3302
|
+
VALUE rb_pgresult = Qnil;
|
3303
|
+
|
3304
|
+
pgconn_discard_results( self );
|
3305
|
+
pgconn_send_describe_portal( self, portal );
|
3306
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3307
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3308
|
+
|
3309
|
+
if ( rb_block_given_p() ) {
|
3310
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3311
|
+
}
|
3312
|
+
return rb_pgresult;
|
3313
|
+
}
|
3314
|
+
|
3315
|
+
|
3316
|
+
/*
|
3317
|
+
* call-seq:
|
3318
|
+
* conn.async_describe_prepared( statement_name ) -> PG::Result
|
3319
|
+
*
|
3320
|
+
* This function has the same behavior as #sync_describe_prepared, but is implemented using the asynchronous command processing API of libpq.
|
3321
|
+
* See #async_exec for the differences between the two API variants.
|
3322
|
+
*/
|
3323
|
+
static VALUE
|
3324
|
+
pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
|
3325
|
+
{
|
3326
|
+
VALUE rb_pgresult = Qnil;
|
3327
|
+
|
3328
|
+
pgconn_discard_results( self );
|
3329
|
+
pgconn_send_describe_prepared( self, stmt_name );
|
3330
|
+
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
3331
|
+
rb_pgresult = pgconn_get_last_result( self );
|
3332
|
+
|
3333
|
+
if ( rb_block_given_p() ) {
|
3334
|
+
return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
|
3335
|
+
}
|
3336
|
+
return rb_pgresult;
|
3337
|
+
}
|
3338
|
+
|
3339
|
+
|
3340
|
+
#ifdef HAVE_PQSSLATTRIBUTE
|
3203
3341
|
/*
|
3204
3342
|
* call-seq:
|
3205
3343
|
* conn.ssl_in_use? -> Boolean
|
3206
3344
|
*
|
3207
3345
|
* Returns +true+ if the connection uses SSL, +false+ if not.
|
3208
3346
|
*
|
3347
|
+
* Available since PostgreSQL-9.5
|
3209
3348
|
*/
|
3210
3349
|
static VALUE
|
3211
3350
|
pgconn_ssl_in_use(VALUE self)
|
@@ -3238,6 +3377,8 @@ pgconn_ssl_in_use(VALUE self)
|
|
3238
3377
|
*
|
3239
3378
|
*
|
3240
3379
|
* See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
|
3380
|
+
*
|
3381
|
+
* Available since PostgreSQL-9.5
|
3241
3382
|
*/
|
3242
3383
|
static VALUE
|
3243
3384
|
pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
@@ -3256,6 +3397,7 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
|
|
3256
3397
|
*
|
3257
3398
|
* See also #ssl_attribute
|
3258
3399
|
*
|
3400
|
+
* Available since PostgreSQL-9.5
|
3259
3401
|
*/
|
3260
3402
|
static VALUE
|
3261
3403
|
pgconn_ssl_attribute_names(VALUE self)
|
@@ -3566,8 +3708,6 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3566
3708
|
}
|
3567
3709
|
|
3568
3710
|
|
3569
|
-
#ifdef M17N_SUPPORTED
|
3570
|
-
|
3571
3711
|
void
|
3572
3712
|
pgconn_set_internal_encoding_index( VALUE self )
|
3573
3713
|
{
|
@@ -3718,7 +3858,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
3718
3858
|
if (( enc = rb_default_internal_encoding() )) {
|
3719
3859
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
3720
3860
|
if ( pgconn_set_client_encoding_async(self, encname) != 0 )
|
3721
|
-
|
3861
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
3722
3862
|
encname, PQerrorMessage(conn) );
|
3723
3863
|
pgconn_set_internal_encoding_index( self );
|
3724
3864
|
return rb_enc_from_encoding( enc );
|
@@ -3729,8 +3869,6 @@ pgconn_set_default_encoding( VALUE self )
|
|
3729
3869
|
}
|
3730
3870
|
|
3731
3871
|
|
3732
|
-
#endif /* M17N_SUPPORTED */
|
3733
|
-
|
3734
3872
|
/*
|
3735
3873
|
* call-seq:
|
3736
3874
|
* res.type_map_for_queries = typemap
|
@@ -3909,6 +4047,20 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
|
|
3909
4047
|
return this->decoder_for_get_copy_data;
|
3910
4048
|
}
|
3911
4049
|
|
4050
|
+
/*
|
4051
|
+
* call-seq:
|
4052
|
+
* res.guess_result_memsize = enabled
|
4053
|
+
*
|
4054
|
+
* This method is for testing only and will probably be removed in the future.
|
4055
|
+
*/
|
4056
|
+
static VALUE
|
4057
|
+
pgconn_guess_result_memsize_set(VALUE self, VALUE enable)
|
4058
|
+
{
|
4059
|
+
t_pg_connection *this = pg_get_connection( self );
|
4060
|
+
this->guess_result_memsize = RTEST(enable);
|
4061
|
+
return enable;
|
4062
|
+
}
|
4063
|
+
|
3912
4064
|
|
3913
4065
|
/*
|
3914
4066
|
* Document-class: PG::Connection
|
@@ -3939,9 +4091,7 @@ init_pg_connection()
|
|
3939
4091
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
3940
4092
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
3941
4093
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
3942
|
-
#ifdef HAVE_PQPING
|
3943
4094
|
rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
|
3944
|
-
#endif
|
3945
4095
|
|
3946
4096
|
/****** PG::Connection INSTANCE METHODS: Connection Control ******/
|
3947
4097
|
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
@@ -3971,43 +4121,42 @@ init_pg_connection()
|
|
3971
4121
|
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
3972
4122
|
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
3973
4123
|
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
3974
|
-
#if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
3975
4124
|
rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
|
3976
|
-
#endif
|
3977
4125
|
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
3978
4126
|
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
3979
4127
|
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
3980
4128
|
/* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
|
3981
4129
|
|
3982
4130
|
/****** PG::Connection INSTANCE METHODS: Command Execution ******/
|
3983
|
-
rb_define_method(rb_cPGconn, "
|
3984
|
-
|
3985
|
-
rb_define_method(rb_cPGconn, "
|
3986
|
-
rb_define_method(rb_cPGconn, "
|
3987
|
-
rb_define_method(rb_cPGconn, "
|
3988
|
-
rb_define_method(rb_cPGconn, "
|
3989
|
-
rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
|
4131
|
+
rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
|
4132
|
+
rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
|
4133
|
+
rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
|
4134
|
+
rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
|
4135
|
+
rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
|
4136
|
+
rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
|
3990
4137
|
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
3991
4138
|
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
3992
4139
|
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
3993
|
-
#ifdef HAVE_PQESCAPELITERAL
|
3994
4140
|
rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
|
3995
|
-
#endif
|
3996
|
-
#ifdef HAVE_PQESCAPEIDENTIFIER
|
3997
4141
|
rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
|
3998
|
-
#endif
|
3999
4142
|
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4000
4143
|
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4001
|
-
#ifdef HAVE_PQSETSINGLEROWMODE
|
4002
4144
|
rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
|
4003
|
-
#endif
|
4004
4145
|
|
4005
4146
|
/****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
|
4006
4147
|
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4148
|
+
rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
|
4149
|
+
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
4150
|
+
rb_define_method(rb_cPGconn, "async_exec_params", pgconn_async_exec_params, -1);
|
4151
|
+
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4007
4152
|
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
4153
|
+
rb_define_method(rb_cPGconn, "async_prepare", pgconn_async_prepare, -1);
|
4008
4154
|
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4155
|
+
rb_define_method(rb_cPGconn, "async_exec_prepared", pgconn_async_exec_prepared, -1);
|
4009
4156
|
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4157
|
+
rb_define_method(rb_cPGconn, "async_describe_prepared", pgconn_async_describe_prepared, 1);
|
4010
4158
|
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4159
|
+
rb_define_method(rb_cPGconn, "async_describe_portal", pgconn_async_describe_portal, 1);
|
4011
4160
|
rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
|
4012
4161
|
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4013
4162
|
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
@@ -4015,6 +4164,7 @@ init_pg_connection()
|
|
4015
4164
|
rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
|
4016
4165
|
rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
|
4017
4166
|
rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
|
4167
|
+
rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
|
4018
4168
|
|
4019
4169
|
/****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4020
4170
|
rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
|
@@ -4031,6 +4181,7 @@ init_pg_connection()
|
|
4031
4181
|
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4032
4182
|
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4033
4183
|
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4184
|
+
rb_define_method(rb_cPGconn, "guess_result_memsize=", pgconn_guess_result_memsize_set, 1);
|
4034
4185
|
|
4035
4186
|
/****** PG::Connection INSTANCE METHODS: Notice Processing ******/
|
4036
4187
|
rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
|
@@ -4045,9 +4196,10 @@ init_pg_connection()
|
|
4045
4196
|
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4046
4197
|
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4047
4198
|
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4048
|
-
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
4049
|
-
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4050
4199
|
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
4200
|
+
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
4201
|
+
rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
|
4202
|
+
#endif
|
4051
4203
|
|
4052
4204
|
#ifdef HAVE_PQSSLATTRIBUTE
|
4053
4205
|
rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
|
@@ -4083,12 +4235,10 @@ init_pg_connection()
|
|
4083
4235
|
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
4084
4236
|
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
4085
4237
|
|
4086
|
-
#ifdef M17N_SUPPORTED
|
4087
4238
|
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
4088
4239
|
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
4089
4240
|
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
4090
4241
|
rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
|
4091
|
-
#endif /* M17N_SUPPORTED */
|
4092
4242
|
|
4093
4243
|
rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
|
4094
4244
|
rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
|