pg 0.21.0 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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);
|