pg 1.1.0 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +0 -6595
  5. data/History.rdoc +110 -1
  6. data/Manifest.txt +3 -2
  7. data/README-Windows.rdoc +4 -4
  8. data/README.ja.rdoc +1 -2
  9. data/README.rdoc +44 -9
  10. data/Rakefile +8 -6
  11. data/Rakefile.cross +57 -56
  12. data/ext/errorcodes.def +68 -0
  13. data/ext/errorcodes.txt +19 -2
  14. data/ext/extconf.rb +6 -6
  15. data/ext/pg.c +138 -99
  16. data/ext/pg.h +34 -26
  17. data/ext/pg_binary_decoder.c +20 -16
  18. data/ext/pg_binary_encoder.c +13 -12
  19. data/ext/pg_coder.c +21 -9
  20. data/ext/pg_connection.c +413 -321
  21. data/ext/pg_copy_coder.c +6 -3
  22. data/ext/pg_record_coder.c +491 -0
  23. data/ext/pg_result.c +282 -128
  24. data/ext/pg_text_decoder.c +14 -8
  25. data/ext/pg_text_encoder.c +180 -48
  26. data/ext/pg_tuple.c +14 -6
  27. data/ext/pg_type_map.c +1 -1
  28. data/ext/pg_type_map_all_strings.c +4 -4
  29. data/ext/pg_type_map_by_class.c +9 -4
  30. data/ext/pg_type_map_by_column.c +7 -6
  31. data/ext/pg_type_map_by_mri_type.c +1 -1
  32. data/ext/pg_type_map_by_oid.c +3 -2
  33. data/ext/pg_type_map_in_ruby.c +1 -1
  34. data/ext/{util.c → pg_util.c} +5 -5
  35. data/ext/{util.h → pg_util.h} +0 -0
  36. data/lib/pg.rb +5 -5
  37. data/lib/pg/basic_type_mapping.rb +81 -18
  38. data/lib/pg/binary_decoder.rb +1 -0
  39. data/lib/pg/coder.rb +22 -1
  40. data/lib/pg/connection.rb +2 -2
  41. data/lib/pg/constants.rb +1 -0
  42. data/lib/pg/exceptions.rb +1 -0
  43. data/lib/pg/result.rb +13 -1
  44. data/lib/pg/text_decoder.rb +2 -3
  45. data/lib/pg/text_encoder.rb +8 -18
  46. data/lib/pg/type_map_by_column.rb +2 -1
  47. data/spec/helpers.rb +19 -19
  48. data/spec/pg/basic_type_mapping_spec.rb +141 -19
  49. data/spec/pg/connection_spec.rb +239 -93
  50. data/spec/pg/result_spec.rb +194 -4
  51. data/spec/pg/tuple_spec.rb +55 -2
  52. data/spec/pg/type_map_by_class_spec.rb +1 -1
  53. data/spec/pg/type_map_by_column_spec.rb +5 -1
  54. data/spec/pg/type_map_by_oid_spec.rb +2 -2
  55. data/spec/pg/type_spec.rb +180 -6
  56. metadata +41 -47
  57. metadata.gz.sig +0 -0
data/ext/pg.h CHANGED
@@ -21,9 +21,6 @@
21
21
  #include "ruby/st.h"
22
22
  #include "ruby/encoding.h"
23
23
 
24
- /* exported by ruby-1.9.3+ but not declared */
25
- extern int rb_enc_alias(const char *, const char *);
26
-
27
24
  #define PG_ENCODING_SET_NOCHECK(obj,i) \
28
25
  do { \
29
26
  if ((i) < ENCODING_INLINE_MAX) \
@@ -81,6 +78,8 @@ typedef long suseconds_t;
81
78
  #define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
82
79
  #endif
83
80
 
81
+ #define PG_ENC_IDX_BITS 28
82
+
84
83
  /* The data behind each PG::Connection object */
85
84
  typedef struct {
86
85
  PGconn *pgconn;
@@ -97,18 +96,19 @@ typedef struct {
97
96
  VALUE type_map_for_results;
98
97
  /* IO object internally used for the trace stream */
99
98
  VALUE trace_stream;
100
- /* Cached Encoding object */
101
- VALUE external_encoding;
102
99
  /* Kind of PG::Coder object for casting ruby values to COPY rows */
103
100
  VALUE encoder_for_put_copy_data;
104
101
  /* Kind of PG::Coder object for casting COPY rows to ruby values */
105
102
  VALUE decoder_for_get_copy_data;
103
+ /* Ruby encoding index of the client/internal encoding */
104
+ int enc_idx : PG_ENC_IDX_BITS;
105
+ /* flags controlling Symbol/String field names */
106
+ unsigned int flags : 2;
106
107
 
107
- /* The connection socket, used for rb_wait_for_single_fd() */
108
- int socket;
109
-
110
- /* enable/disable guessing size of PGresult's allocated memory */
111
- int guess_result_memsize;
108
+ #if defined(_WIN32)
109
+ /* File descriptor to be used for rb_w32_unwrap_io_handle() */
110
+ int ruby_sd;
111
+ #endif
112
112
  } t_pg_connection;
113
113
 
114
114
  typedef struct pg_coder t_pg_coder;
@@ -129,10 +129,16 @@ typedef struct {
129
129
  */
130
130
  t_typemap *p_typemap;
131
131
 
132
+ /* Ruby encoding index of the client/internal encoding */
133
+ int enc_idx : PG_ENC_IDX_BITS;
134
+
132
135
  /* 0 = PGresult is cleared by PG::Result#clear or by the GC
133
136
  * 1 = PGresult is cleared internally by libpq
134
137
  */
135
- int autoclear;
138
+ unsigned int autoclear : 1;
139
+
140
+ /* flags controlling Symbol/String field names */
141
+ unsigned int flags : 2;
136
142
 
137
143
  /* Number of fields in fnames[] .
138
144
  * Set to -1 if fnames[] is not yet initialized.
@@ -148,7 +154,7 @@ typedef struct {
148
154
  /* Hash with fnames[] to field number mapping. */
149
155
  VALUE field_map;
150
156
 
151
- /* List of field names as frozen String objects.
157
+ /* List of field names as frozen String or Symbol objects.
152
158
  * Only valid if nfields != -1
153
159
  */
154
160
  VALUE fnames[0];
@@ -164,6 +170,10 @@ typedef VALUE (* t_pg_typecast_result)(t_typemap *, VALUE, int, int);
164
170
  typedef t_pg_coder *(* t_pg_typecast_query_param)(t_typemap *, VALUE, int);
165
171
  typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
166
172
 
173
+ #define PG_RESULT_FIELD_NAMES_MASK 0x03
174
+ #define PG_RESULT_FIELD_NAMES_SYMBOL 0x01
175
+ #define PG_RESULT_FIELD_NAMES_STATIC_SYMBOL 0x02
176
+
167
177
  #define PG_CODER_TIMESTAMP_DB_UTC 0x0
168
178
  #define PG_CODER_TIMESTAMP_DB_LOCAL 0x1
169
179
  #define PG_CODER_TIMESTAMP_APP_UTC 0x0
@@ -276,6 +286,7 @@ void init_pg_type_map_by_oid _(( void ));
276
286
  void init_pg_type_map_in_ruby _(( void ));
277
287
  void init_pg_coder _(( void ));
278
288
  void init_pg_copycoder _(( void ));
289
+ void init_pg_recordcoder _(( void ));
279
290
  void init_pg_text_encoder _(( void ));
280
291
  void init_pg_text_decoder _(( void ));
281
292
  void init_pg_binary_encoder _(( void ));
@@ -293,6 +304,7 @@ VALUE pg_obj_to_i _(( VALUE ));
293
304
  VALUE pg_tmbc_allocate _(( void ));
294
305
  void pg_coder_init_encoder _(( VALUE ));
295
306
  void pg_coder_init_decoder _(( VALUE ));
307
+ void pg_coder_mark _(( t_pg_coder * ));
296
308
  char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
297
309
 
298
310
  #define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
@@ -306,11 +318,6 @@ char *pg_rb_str_ensure_capa _(( VALUE, long, char *,
306
318
  (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
307
319
  )
308
320
 
309
- #define PG_RB_TAINTED_STR_NEW( str, curr_ptr, end_ptr ) ( \
310
- (str) = rb_tainted_str_new( NULL, 0 ), \
311
- (curr_ptr) = (end_ptr) = RSTRING_PTR(str) \
312
- )
313
-
314
321
  VALUE pg_typemap_fit_to_result _(( VALUE, VALUE ));
315
322
  VALUE pg_typemap_fit_to_query _(( VALUE, VALUE ));
316
323
  int pg_typemap_fit_to_copy_get _(( VALUE ));
@@ -334,12 +341,7 @@ VALUE pg_tuple_new _(( VALUE, int ));
334
341
  static inline t_pg_result *
335
342
  pgresult_get_this( VALUE self )
336
343
  {
337
- t_pg_result *this = RTYPEDDATA_DATA(self);
338
-
339
- if( this == NULL )
340
- rb_raise(rb_ePGerror, "result has been cleared");
341
-
342
- return this;
344
+ return RTYPEDDATA_DATA(self);
343
345
  }
344
346
 
345
347
 
@@ -351,10 +353,16 @@ rb_encoding *pg_conn_enc_get _(( PGconn * ));
351
353
  void notice_receiver_proxy(void *arg, const PGresult *result);
352
354
  void notice_processor_proxy(void *arg, const char *message);
353
355
 
354
- /* reports if `-W' specified and PG_SKIP_DEPRECATION_WARNING environment variable isn't set */
355
- #define pg_deprecated(x) \
356
+ /* reports if `-W' specified and PG_SKIP_DEPRECATION_WARNING environment variable isn't set
357
+ *
358
+ * message_id identifies the warning, so that it's reported only once.
359
+ */
360
+ #define pg_deprecated(message_id, format_args) \
356
361
  do { \
357
- if( !pg_skip_deprecation_warning ) rb_warning x; \
362
+ if( !(pg_skip_deprecation_warning & (1 << message_id)) ){ \
363
+ pg_skip_deprecation_warning |= 1 << message_id; \
364
+ rb_warning format_args; \
365
+ } \
358
366
  } while(0);
359
367
 
360
368
  #endif /* end __pg_h */
@@ -1,12 +1,12 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_decoder.c,v 5d166a4d0441 2018/07/29 12:03:00 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
7
7
  #include "ruby/version.h"
8
8
  #include "pg.h"
9
- #include "util.h"
9
+ #include "pg_util.h"
10
10
  #ifdef HAVE_INTTYPES_H
11
11
  #include <inttypes.h>
12
12
  #endif
@@ -17,8 +17,8 @@ VALUE rb_mPG_BinaryDecoder;
17
17
  /*
18
18
  * Document-class: PG::BinaryDecoder::Boolean < PG::SimpleDecoder
19
19
  *
20
- * This is a decoder class for conversion of PostgreSQL binary bool type
21
- * to Ruby true or false objects.
20
+ * This is a decoder class for conversion of PostgreSQL binary +bool+ type
21
+ * to Ruby +true+ or +false+ objects.
22
22
  *
23
23
  */
24
24
  static VALUE
@@ -33,7 +33,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int fi
33
33
  /*
34
34
  * Document-class: PG::BinaryDecoder::Integer < PG::SimpleDecoder
35
35
  *
36
- * This is a decoder class for conversion of PostgreSQL binary int2, int4 and int8 types
36
+ * This is a decoder class for conversion of PostgreSQL binary +int2+, +int4+ and +int8+ types
37
37
  * to Ruby Integer objects.
38
38
  *
39
39
  */
@@ -55,7 +55,7 @@ pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int fi
55
55
  /*
56
56
  * Document-class: PG::BinaryDecoder::Float < PG::SimpleDecoder
57
57
  *
58
- * This is a decoder class for conversion of PostgreSQL binary float4 and float8 types
58
+ * This is a decoder class for conversion of PostgreSQL binary +float4+ and +float8+ types
59
59
  * to Ruby Float objects.
60
60
  *
61
61
  */
@@ -87,7 +87,7 @@ pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
87
87
  * Document-class: PG::BinaryDecoder::Bytea < PG::SimpleDecoder
88
88
  *
89
89
  * This decoder class delivers the data received from the server as binary String object.
90
- * It is therefore suitable for conversion of PostgreSQL bytea data as well as any other
90
+ * It is therefore suitable for conversion of PostgreSQL +bytea+ data as well as any other
91
91
  * data in binary format.
92
92
  *
93
93
  */
@@ -95,7 +95,7 @@ VALUE
95
95
  pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
96
96
  {
97
97
  VALUE ret;
98
- ret = rb_tainted_str_new( val, len );
98
+ ret = rb_str_new( val, len );
99
99
  PG_ENCODING_SET_NOCHECK( ret, rb_ascii8bit_encindex() );
100
100
  return ret;
101
101
  }
@@ -103,7 +103,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
103
103
  /*
104
104
  * Document-class: PG::BinaryDecoder::ToBase64 < PG::CompositeDecoder
105
105
  *
106
- * This is a decoder class for conversion of binary (bytea) to base64 data.
106
+ * This is a decoder class for conversion of binary +bytea+ to base64 data.
107
107
  *
108
108
  */
109
109
  static VALUE
@@ -113,7 +113,7 @@ pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int
113
113
  t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
114
114
  int encoded_len = BASE64_ENCODED_SIZE(len);
115
115
  /* create a buffer of the encoded length */
116
- VALUE out_value = rb_tainted_str_new(NULL, encoded_len);
116
+ VALUE out_value = rb_str_new(NULL, encoded_len);
117
117
 
118
118
  base64_encode( RSTRING_PTR(out_value), val, len );
119
119
 
@@ -154,7 +154,8 @@ static VALUE
154
154
  pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
155
155
  {
156
156
  int64_t timestamp;
157
- struct timespec ts;
157
+ int64_t sec;
158
+ int64_t nsec;
158
159
  VALUE t;
159
160
 
160
161
  if( len != sizeof(timestamp) ){
@@ -171,14 +172,17 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
171
172
  default:
172
173
  /* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
173
174
  * Adjust the 30 years difference. */
174
- ts.tv_sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
175
- ts.tv_nsec = (timestamp % 1000000) * 1000;
175
+ sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
176
+ nsec = (timestamp % 1000000) * 1000;
176
177
 
177
- #if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T)
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
178
179
  /* Fast path for time conversion */
179
- t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
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
+ }
180
184
  #else
181
- t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(ts.tv_sec), LL2NUM(ts.tv_nsec / 1000));
185
+ t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(sec), LL2NUM(nsec / 1000));
182
186
  if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
183
187
  t = rb_funcall(t, rb_intern("utc"), 0);
184
188
  }
@@ -1,11 +1,11 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_encoder.c,v e61a06f1f5ed 2015/12/25 21:14:21 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
- #include "util.h"
8
+ #include "pg_util.h"
9
9
  #ifdef HAVE_INTTYPES_H
10
10
  #include <inttypes.h>
11
11
  #endif
@@ -25,11 +25,12 @@ static int
25
25
  pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
26
26
  {
27
27
  char mybool;
28
- switch(value){
29
- case Qtrue : mybool = 1; break;
30
- case Qfalse : mybool = 0; break;
31
- default :
32
- rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
28
+ if (value == Qtrue) {
29
+ mybool = 1;
30
+ } else if (value == Qfalse) {
31
+ mybool = 0;
32
+ } else {
33
+ rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
33
34
  }
34
35
  if(out) *out = mybool;
35
36
  return 1;
@@ -38,7 +39,7 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
38
39
  /*
39
40
  * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
40
41
  *
41
- * This is the encoder class for the PostgreSQL int2 type.
42
+ * This is the encoder class for the PostgreSQL +int2+ (alias +smallint+) type.
42
43
  *
43
44
  * Non-Number values are expected to have method +to_i+ defined.
44
45
  *
@@ -55,9 +56,9 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
55
56
  }
56
57
 
57
58
  /*
58
- * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
59
+ * Document-class: PG::BinaryEncoder::Int4 < PG::SimpleEncoder
59
60
  *
60
- * This is the encoder class for the PostgreSQL int4 type.
61
+ * This is the encoder class for the PostgreSQL +int4+ (alias +integer+) type.
61
62
  *
62
63
  * Non-Number values are expected to have method +to_i+ defined.
63
64
  *
@@ -74,9 +75,9 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
74
75
  }
75
76
 
76
77
  /*
77
- * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
78
+ * Document-class: PG::BinaryEncoder::Int8 < PG::SimpleEncoder
78
79
  *
79
- * This is the encoder class for the PostgreSQL int8 type.
80
+ * This is the encoder class for the PostgreSQL +int8+ (alias +bigint+) type.
80
81
  *
81
82
  * Non-Number values are expected to have method +to_i+ defined.
82
83
  *
@@ -61,11 +61,23 @@ pg_coder_init_decoder( VALUE self )
61
61
  rb_iv_set( self, "@name", Qnil );
62
62
  }
63
63
 
64
+ void
65
+ pg_coder_mark(t_pg_coder *this)
66
+ {
67
+ rb_gc_mark(this->coder_obj);
68
+ }
69
+
70
+ static void
71
+ pg_composite_coder_mark(t_pg_composite_coder *this)
72
+ {
73
+ pg_coder_mark(&this->comp);
74
+ }
75
+
64
76
  static VALUE
65
77
  pg_simple_encoder_allocate( VALUE klass )
66
78
  {
67
79
  t_pg_coder *this;
68
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
80
+ VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
69
81
  pg_coder_init_encoder( self );
70
82
  return self;
71
83
  }
@@ -74,7 +86,7 @@ static VALUE
74
86
  pg_composite_encoder_allocate( VALUE klass )
75
87
  {
76
88
  t_pg_composite_coder *this;
77
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
89
+ VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
78
90
  pg_coder_init_encoder( self );
79
91
  this->elem = NULL;
80
92
  this->needs_quotation = 1;
@@ -87,7 +99,7 @@ static VALUE
87
99
  pg_simple_decoder_allocate( VALUE klass )
88
100
  {
89
101
  t_pg_coder *this;
90
- VALUE self = Data_Make_Struct( klass, t_pg_coder, NULL, -1, this );
102
+ VALUE self = Data_Make_Struct( klass, t_pg_coder, pg_coder_mark, -1, this );
91
103
  pg_coder_init_decoder( self );
92
104
  return self;
93
105
  }
@@ -96,7 +108,7 @@ static VALUE
96
108
  pg_composite_decoder_allocate( VALUE klass )
97
109
  {
98
110
  t_pg_composite_coder *this;
99
- VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, NULL, -1, this );
111
+ VALUE self = Data_Make_Struct( klass, t_pg_composite_coder, pg_composite_coder_mark, -1, this );
100
112
  pg_coder_init_decoder( self );
101
113
  this->elem = NULL;
102
114
  this->needs_quotation = 1;
@@ -145,7 +157,6 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
145
157
 
146
158
  if( len == -1 ){
147
159
  /* The intermediate value is a String that can be used directly. */
148
- OBJ_INFECT(intermediate, value);
149
160
  return intermediate;
150
161
  }
151
162
 
@@ -157,7 +168,6 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
157
168
  rb_obj_classname( self ), len, len2 );
158
169
  }
159
170
  rb_str_set_len( res, len2 );
160
- OBJ_INFECT(res, value);
161
171
 
162
172
  RB_GC_GUARD(intermediate);
163
173
 
@@ -204,7 +214,6 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
204
214
  }
205
215
 
206
216
  res = this->dec_func(this, val, RSTRING_LEN(argv[0]), tuple, field, ENCODING_GET(argv[0]));
207
- OBJ_INFECT(res, argv[0]);
208
217
 
209
218
  return res;
210
219
  }
@@ -400,6 +409,11 @@ pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
400
409
  if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
401
410
  rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
402
411
 
412
+ if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_TextEncoder )
413
+ rb_define_method( coder_klass, "encode", pg_coder_encode, -1 );
414
+ if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
415
+ rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
416
+
403
417
  rb_define_const( coder_klass, "CFUNC", cfunc_obj );
404
418
 
405
419
  RB_GC_GUARD(cfunc_obj);
@@ -512,8 +526,6 @@ init_pg_coder()
512
526
  * This accessor is only used in PG::Coder#inspect .
513
527
  */
514
528
  rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
515
- rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, -1 );
516
- rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
517
529
 
518
530
  /* Document-class: PG::SimpleCoder < PG::Coder */
519
531
  rb_cPG_SimpleCoder = rb_define_class_under( rb_mPG, "SimpleCoder", rb_cPG_Coder );
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v e57f6b452eb3 2018/08/18 10:58:52 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -13,13 +13,14 @@
13
13
  VALUE rb_cPGconn;
14
14
  static ID s_id_encode;
15
15
  static VALUE sym_type, sym_format, sym_value;
16
+ static VALUE sym_symbol, sym_string, sym_static_symbol;
16
17
 
17
18
  static PQnoticeReceiver default_notice_receiver = NULL;
18
19
  static PQnoticeProcessor default_notice_processor = NULL;
19
20
 
20
21
  static VALUE pgconn_finish( VALUE );
21
22
  static VALUE pgconn_set_default_encoding( VALUE self );
22
- void pgconn_set_internal_encoding_index( VALUE );
23
+ static void pgconn_set_internal_encoding_index( VALUE );
23
24
 
24
25
  /*
25
26
  * Global functions
@@ -85,8 +86,7 @@ pgconn_close_socket_io( VALUE self )
85
86
 
86
87
  if ( RTEST(socket_io) ) {
87
88
  #if defined(_WIN32)
88
- int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
89
- if( rb_w32_unwrap_io_handle(ruby_sd) ){
89
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
90
90
  rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
91
91
  }
92
92
  #endif
@@ -153,7 +153,6 @@ pgconn_gc_mark( t_pg_connection *this )
153
153
  rb_gc_mark( this->type_map_for_queries );
154
154
  rb_gc_mark( this->type_map_for_results );
155
155
  rb_gc_mark( this->trace_stream );
156
- rb_gc_mark( this->external_encoding );
157
156
  rb_gc_mark( this->encoder_for_put_copy_data );
158
157
  rb_gc_mark( this->decoder_for_get_copy_data );
159
158
  }
@@ -165,6 +164,10 @@ pgconn_gc_mark( t_pg_connection *this )
165
164
  static void
166
165
  pgconn_gc_free( t_pg_connection *this )
167
166
  {
167
+ #if defined(_WIN32)
168
+ if ( RTEST(this->socket_io) )
169
+ rb_w32_unwrap_io_handle( this->ruby_sd );
170
+ #endif
168
171
  if (this->pgconn != NULL)
169
172
  PQfinish( this->pgconn );
170
173
 
@@ -197,9 +200,6 @@ pgconn_s_allocate( VALUE klass )
197
200
  this->encoder_for_put_copy_data = Qnil;
198
201
  this->decoder_for_get_copy_data = Qnil;
199
202
  this->trace_stream = Qnil;
200
- this->external_encoding = Qnil;
201
- this->socket = -1;
202
- this->guess_result_memsize = 1;
203
203
 
204
204
  return self;
205
205
  }
@@ -216,32 +216,27 @@ pgconn_s_allocate( VALUE klass )
216
216
  *
217
217
  * Create a connection to the specified server.
218
218
  *
219
+ * +connection_hash+ must be a ruby Hash with connection parameters.
220
+ * See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
221
+ *
222
+ * There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
223
+ * See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
224
+ *
225
+ * The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
219
226
  * [+host+]
220
227
  * server hostname
221
- * [+hostaddr+]
222
- * server address (avoids hostname lookup, overrides +host+)
223
228
  * [+port+]
224
229
  * server port number
230
+ * [+options+]
231
+ * backend options
232
+ * [+tty+]
233
+ * (ignored in newer versions of PostgreSQL)
225
234
  * [+dbname+]
226
235
  * connecting database name
227
236
  * [+user+]
228
237
  * login user name
229
238
  * [+password+]
230
239
  * login password
231
- * [+connect_timeout+]
232
- * maximum time to wait for connection to succeed
233
- * [+options+]
234
- * backend options
235
- * [+tty+]
236
- * (ignored in newer versions of PostgreSQL)
237
- * [+sslmode+]
238
- * (disable|allow|prefer|require)
239
- * [+krbsrvname+]
240
- * kerberos service name
241
- * [+gsslib+]
242
- * GSS library to use for GSSAPI authentication
243
- * [+service+]
244
- * service name to use for additional parameters
245
240
  *
246
241
  * Examples:
247
242
  *
@@ -257,7 +252,7 @@ pgconn_s_allocate( VALUE klass )
257
252
  * # As an Array
258
253
  * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
259
254
  *
260
- * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
255
+ * If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
261
256
  * connection will have its +client_encoding+ set accordingly.
262
257
  *
263
258
  * Raises a PG::Error if the connection fails.
@@ -272,6 +267,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
272
267
  this = pg_get_connection( self );
273
268
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
274
269
  this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
270
+
275
271
  if(this->pgconn == NULL)
276
272
  rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
277
273
 
@@ -281,10 +277,6 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
281
277
  rb_exc_raise(error);
282
278
  }
283
279
 
284
- this->socket = PQsocket( this->pgconn );
285
- if ( this->socket < 0 )
286
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
287
-
288
280
  pgconn_set_default_encoding( self );
289
281
 
290
282
  if (rb_block_given_p()) {
@@ -299,14 +291,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
299
291
  * PG::Connection.connect_start(connection_string) -> conn
300
292
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
301
293
  *
302
- * This is an asynchronous version of PG::Connection.connect().
294
+ * This is an asynchronous version of PG::Connection.new.
303
295
  *
304
296
  * Use #connect_poll to poll the status of the connection.
305
297
  *
306
298
  * NOTE: this does *not* set the connection's +client_encoding+ for you if
307
- * Encoding.default_internal is set. To set it after the connection is established,
299
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
308
300
  * call #internal_encoding=. You can also set it automatically by setting
309
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
301
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
302
+ *
303
+ * See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
310
304
  *
311
305
  */
312
306
  static VALUE
@@ -335,10 +329,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
335
329
  rb_exc_raise(error);
336
330
  }
337
331
 
338
- this->socket = PQsocket( this->pgconn );
339
- if ( this->socket < 0 )
340
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
341
-
342
332
  if ( rb_block_given_p() ) {
343
333
  return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
344
334
  }
@@ -353,6 +343,8 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
353
343
  *
354
344
  * Check server status.
355
345
  *
346
+ * See PG::Connection.new for a description of the parameters.
347
+ *
356
348
  * Returns one of:
357
349
  * [+PQPING_OK+]
358
350
  * server is accepting connections
@@ -362,8 +354,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
362
354
  * could not establish connection
363
355
  * [+PQPING_NO_ATTEMPT+]
364
356
  * connection not attempted (bad params)
365
- *
366
- * Available since PostgreSQL-9.1
367
357
  */
368
358
  static VALUE
369
359
  pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
@@ -434,7 +424,8 @@ pgconn_s_conndefaults(VALUE self)
434
424
  * Return value is the encrypted password.
435
425
  * The caller can assume the string doesn't contain any special characters that would require escaping.
436
426
  *
437
- * Available since PostgreSQL-10
427
+ * Available since PostgreSQL-10.
428
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
438
429
  */
439
430
  static VALUE
440
431
  pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
@@ -453,10 +444,6 @@ pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
453
444
  if ( encrypted ) {
454
445
  rval = rb_str_new2( encrypted );
455
446
  PQfreemem( encrypted );
456
-
457
- OBJ_INFECT( rval, password );
458
- OBJ_INFECT( rval, username );
459
- OBJ_INFECT( rval, algorithm );
460
447
  } else {
461
448
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
462
449
  }
@@ -489,9 +476,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
489
476
  rval = rb_str_new2( encrypted );
490
477
  PQfreemem( encrypted );
491
478
 
492
- OBJ_INFECT( rval, password );
493
- OBJ_INFECT( rval, username );
494
-
495
479
  return rval;
496
480
  }
497
481
 
@@ -637,7 +621,7 @@ pgconn_db(VALUE self)
637
621
  {
638
622
  char *db = PQdb(pg_get_pgconn(self));
639
623
  if (!db) return Qnil;
640
- return rb_tainted_str_new2(db);
624
+ return rb_str_new2(db);
641
625
  }
642
626
 
643
627
  /*
@@ -651,7 +635,7 @@ pgconn_user(VALUE self)
651
635
  {
652
636
  char *user = PQuser(pg_get_pgconn(self));
653
637
  if (!user) return Qnil;
654
- return rb_tainted_str_new2(user);
638
+ return rb_str_new2(user);
655
639
  }
656
640
 
657
641
  /*
@@ -665,7 +649,7 @@ pgconn_pass(VALUE self)
665
649
  {
666
650
  char *user = PQpass(pg_get_pgconn(self));
667
651
  if (!user) return Qnil;
668
- return rb_tainted_str_new2(user);
652
+ return rb_str_new2(user);
669
653
  }
670
654
 
671
655
  /*
@@ -679,7 +663,7 @@ pgconn_host(VALUE self)
679
663
  {
680
664
  char *host = PQhost(pg_get_pgconn(self));
681
665
  if (!host) return Qnil;
682
- return rb_tainted_str_new2(host);
666
+ return rb_str_new2(host);
683
667
  }
684
668
 
685
669
  /*
@@ -706,7 +690,7 @@ pgconn_tty(VALUE self)
706
690
  {
707
691
  char *tty = PQtty(pg_get_pgconn(self));
708
692
  if (!tty) return Qnil;
709
- return rb_tainted_str_new2(tty);
693
+ return rb_str_new2(tty);
710
694
  }
711
695
 
712
696
  /*
@@ -720,7 +704,7 @@ pgconn_options(VALUE self)
720
704
  {
721
705
  char *options = PQoptions(pg_get_pgconn(self));
722
706
  if (!options) return Qnil;
723
- return rb_tainted_str_new2(options);
707
+ return rb_str_new2(options);
724
708
  }
725
709
 
726
710
 
@@ -801,7 +785,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
801
785
  if(ret == NULL)
802
786
  return Qnil;
803
787
  else
804
- return rb_tainted_str_new2(ret);
788
+ return rb_str_new2(ret);
805
789
  }
806
790
 
807
791
  /*
@@ -846,7 +830,7 @@ pgconn_error_message(VALUE self)
846
830
  {
847
831
  char *error = PQerrorMessage(pg_get_pgconn(self));
848
832
  if (!error) return Qnil;
849
- return rb_tainted_str_new2(error);
833
+ return rb_str_new2(error);
850
834
  }
851
835
 
852
836
  /*
@@ -870,6 +854,8 @@ static VALUE
870
854
  pgconn_socket(VALUE self)
871
855
  {
872
856
  int sd;
857
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
858
+
873
859
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
874
860
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
875
861
  return INT2NUM(sd);
@@ -902,6 +888,7 @@ pgconn_socket_io(VALUE self)
902
888
 
903
889
  #ifdef _WIN32
904
890
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
891
+ this->ruby_sd = ruby_sd;
905
892
  #else
906
893
  ruby_sd = sd;
907
894
  #endif
@@ -965,32 +952,23 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
965
952
 
966
953
  /*
967
954
  * call-seq:
968
- * conn.exec(sql) -> PG::Result
969
- * conn.exec(sql) {|pg_result| block }
955
+ * conn.sync_exec(sql) -> PG::Result
956
+ * conn.sync_exec(sql) {|pg_result| block }
970
957
  *
971
- * Sends SQL query request specified by _sql_ to PostgreSQL.
972
- * Returns a PG::Result instance on success.
973
- * On failure, it raises a PG::Error.
958
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
959
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
974
960
  *
975
- * For backward compatibility, if you pass more than one parameter to this method,
976
- * it will call #exec_params for you. New code should explicitly use #exec_params if
977
- * argument placeholders are used.
978
- *
979
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
980
- * and the PG::Result object will automatically be cleared when the block terminates.
981
- * In this instance, <code>conn.exec</code> returns the value of the block.
961
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
962
+ * However #async_exec has two advantages:
982
963
  *
983
- * #sync_exec is implemented on the synchronous command processing API of libpq, whereas
984
- * #async_exec is implemented on the asynchronous API.
985
- * #sync_exec is somewhat faster that #async_exec, but blocks any signals to be processed until
986
- * the query is finished. This is most notably visible by a delayed reaction to Control+C.
987
- * Both methods ensure that other threads can process while waiting for the server to
988
- * complete the request.
964
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
965
+ * 2. Ruby VM gets notified about IO blocked operations.
966
+ * It can therefore schedule things like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
989
967
  */
990
968
  static VALUE
991
969
  pgconn_exec(int argc, VALUE *argv, VALUE self)
992
970
  {
993
- PGconn *conn = pg_get_pgconn(self);
971
+ t_pg_connection *this = pg_get_connection_safe( self );
994
972
  PGresult *result = NULL;
995
973
  VALUE rb_pgresult;
996
974
 
@@ -998,7 +976,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
998
976
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
999
977
  VALUE query_str = argv[0];
1000
978
 
1001
- result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
979
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
1002
980
  rb_pgresult = pg_new_result(result, self);
1003
981
  pg_result_check(rb_pgresult);
1004
982
  if (rb_block_given_p()) {
@@ -1006,7 +984,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
1006
984
  }
1007
985
  return rb_pgresult;
1008
986
  }
1009
- pg_deprecated(("forwarding exec to exec_params is deprecated"));
987
+ pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
1010
988
 
1011
989
  /* Otherwise, just call #exec_params instead for backward-compatibility */
1012
990
  return pgconn_exec_params( argc, argv, self );
@@ -1260,57 +1238,23 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1260
1238
 
1261
1239
  /*
1262
1240
  * call-seq:
1263
- * conn.exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1264
- * conn.exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1241
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1242
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1265
1243
  *
1266
- * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
1267
- * for parameters.
1268
- *
1269
- * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
1270
- *
1271
- * +params+ is an array of the bind parameters for the SQL query.
1272
- * Each element of the +params+ array may be either:
1273
- * a hash of the form:
1274
- * {:value => String (value of bind parameter)
1275
- * :type => Integer (oid of type of bind parameter)
1276
- * :format => Integer (0 for text, 1 for binary)
1277
- * }
1278
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1279
- * { :value => <string value>, :type => 0, :format => 0 }
1280
- *
1281
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1282
- * inside the SQL query. The 0th element of the +params+ array is bound
1283
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1284
- *
1285
- * If the types are not specified, they will be inferred by PostgreSQL.
1286
- * Instead of specifying type oids, it's recommended to simply add
1287
- * explicit casts in the query to ensure that the right type is used.
1288
- *
1289
- * For example: "SELECT $1::int"
1290
- *
1291
- * The optional +result_format+ should be 0 for text results, 1
1292
- * for binary.
1293
- *
1294
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1295
- * This will type cast the params from various Ruby types before transmission
1296
- * based on the encoders defined by the type map. When a type encoder is used
1297
- * the format and oid of a given bind parameter are retrieved from the encoder
1298
- * instead out of the hash form described above.
1299
- *
1300
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1301
- * and the PG::Result object will automatically be cleared when the block terminates.
1302
- * In this instance, <code>conn.exec</code> returns the value of the block.
1244
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1245
+ * See #async_exec for the differences between the two API variants.
1246
+ * It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
1303
1247
  */
1304
1248
  static VALUE
1305
1249
  pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1306
1250
  {
1307
- PGconn *conn = pg_get_pgconn(self);
1251
+ t_pg_connection *this = pg_get_connection_safe( self );
1308
1252
  PGresult *result = NULL;
1309
1253
  VALUE rb_pgresult;
1310
1254
  VALUE command, in_res_fmt;
1311
1255
  int nParams;
1312
1256
  int resultFormat;
1313
- struct query_params_data paramsData = { ENCODING_GET(self) };
1257
+ struct query_params_data paramsData = { this->enc_idx };
1314
1258
 
1315
1259
  /* For compatibility we accept 1 to 4 parameters */
1316
1260
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
@@ -1321,7 +1265,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1321
1265
  * is passed to #exec
1322
1266
  */
1323
1267
  if ( NIL_P(paramsData.params) ) {
1324
- pg_deprecated(("forwarding exec_params to exec is deprecated"));
1268
+ pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1325
1269
  return pgconn_exec( 1, argv, self );
1326
1270
  }
1327
1271
  pgconn_query_assign_typemap( self, &paramsData );
@@ -1329,7 +1273,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1329
1273
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1330
1274
  nParams = alloc_query_params( &paramsData );
1331
1275
 
1332
- result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1276
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1333
1277
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1334
1278
 
1335
1279
  free_query_params( &paramsData );
@@ -1346,28 +1290,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1346
1290
 
1347
1291
  /*
1348
1292
  * call-seq:
1349
- * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1293
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1350
1294
  *
1351
- * Prepares statement _sql_ with name _name_ to be executed later.
1352
- * Returns a PG::Result instance on success.
1353
- * On failure, it raises a PG::Error.
1354
- *
1355
- * +param_types+ is an optional parameter to specify the Oids of the
1356
- * types of the parameters.
1357
- *
1358
- * If the types are not specified, they will be inferred by PostgreSQL.
1359
- * Instead of specifying type oids, it's recommended to simply add
1360
- * explicit casts in the query to ensure that the right type is used.
1361
- *
1362
- * For example: "SELECT $1::int"
1363
- *
1364
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1365
- * inside the SQL query.
1295
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1296
+ * See #async_exec for the differences between the two API variants.
1297
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1366
1298
  */
1367
1299
  static VALUE
1368
1300
  pgconn_prepare(int argc, VALUE *argv, VALUE self)
1369
1301
  {
1370
- PGconn *conn = pg_get_pgconn(self);
1302
+ t_pg_connection *this = pg_get_connection_safe( self );
1371
1303
  PGresult *result = NULL;
1372
1304
  VALUE rb_pgresult;
1373
1305
  VALUE name, command, in_paramtypes;
@@ -1377,7 +1309,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1377
1309
  Oid *paramTypes = NULL;
1378
1310
  const char *name_cstr;
1379
1311
  const char *command_cstr;
1380
- int enc_idx = ENCODING_GET(self);
1312
+ int enc_idx = this->enc_idx;
1381
1313
 
1382
1314
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1383
1315
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1395,7 +1327,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1395
1327
  paramTypes[i] = NUM2UINT(param);
1396
1328
  }
1397
1329
  }
1398
- result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1330
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1399
1331
 
1400
1332
  xfree(paramTypes);
1401
1333
 
@@ -1406,49 +1338,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1406
1338
 
1407
1339
  /*
1408
1340
  * call-seq:
1409
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1410
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1341
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1342
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1411
1343
  *
1412
- * Execute prepared named statement specified by _statement_name_.
1413
- * Returns a PG::Result instance on success.
1414
- * On failure, it raises a PG::Error.
1415
- *
1416
- * +params+ is an array of the optional bind parameters for the
1417
- * SQL query. Each element of the +params+ array may be either:
1418
- * a hash of the form:
1419
- * {:value => String (value of bind parameter)
1420
- * :format => Integer (0 for text, 1 for binary)
1421
- * }
1422
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1423
- * { :value => <string value>, :format => 0 }
1424
- *
1425
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1426
- * inside the SQL query. The 0th element of the +params+ array is bound
1427
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1428
- *
1429
- * The optional +result_format+ should be 0 for text results, 1
1430
- * for binary.
1431
- *
1432
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1433
- * This will type cast the params from various Ruby types before transmission
1434
- * based on the encoders defined by the type map. When a type encoder is used
1435
- * the format and oid of a given bind parameter are retrieved from the encoder
1436
- * instead out of the hash form described above.
1437
- *
1438
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1439
- * and the PG::Result object will automatically be cleared when the block terminates.
1440
- * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1344
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1345
+ * See #async_exec for the differences between the two API variants.
1346
+ * It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
1441
1347
  */
1442
1348
  static VALUE
1443
1349
  pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1444
1350
  {
1445
- PGconn *conn = pg_get_pgconn(self);
1351
+ t_pg_connection *this = pg_get_connection_safe( self );
1446
1352
  PGresult *result = NULL;
1447
1353
  VALUE rb_pgresult;
1448
1354
  VALUE name, in_res_fmt;
1449
1355
  int nParams;
1450
1356
  int resultFormat;
1451
- struct query_params_data paramsData = { ENCODING_GET(self) };
1357
+ struct query_params_data paramsData = { this->enc_idx };
1452
1358
 
1453
1359
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1454
1360
  paramsData.with_types = 0;
@@ -1461,7 +1367,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1461
1367
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1462
1368
  nParams = alloc_query_params( &paramsData );
1463
1369
 
1464
- result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1370
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1465
1371
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1466
1372
  resultFormat);
1467
1373
 
@@ -1478,25 +1384,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1478
1384
 
1479
1385
  /*
1480
1386
  * call-seq:
1481
- * conn.describe_prepared( statement_name ) -> PG::Result
1387
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1482
1388
  *
1483
- * Retrieve information about the prepared statement
1484
- * _statement_name_.
1389
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1390
+ * See #async_exec for the differences between the two API variants.
1391
+ * It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
1485
1392
  */
1486
1393
  static VALUE
1487
1394
  pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1488
1395
  {
1489
1396
  PGresult *result;
1490
1397
  VALUE rb_pgresult;
1491
- PGconn *conn = pg_get_pgconn(self);
1398
+ t_pg_connection *this = pg_get_connection_safe( self );
1492
1399
  const char *stmt;
1493
1400
  if(NIL_P(stmt_name)) {
1494
1401
  stmt = NULL;
1495
1402
  }
1496
1403
  else {
1497
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1404
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1498
1405
  }
1499
- result = gvl_PQdescribePrepared(conn, stmt);
1406
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1500
1407
  rb_pgresult = pg_new_result(result, self);
1501
1408
  pg_result_check(rb_pgresult);
1502
1409
  return rb_pgresult;
@@ -1505,9 +1412,11 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1505
1412
 
1506
1413
  /*
1507
1414
  * call-seq:
1508
- * conn.describe_portal( portal_name ) -> PG::Result
1415
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1509
1416
  *
1510
- * Retrieve information about the portal _portal_name_.
1417
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1418
+ * See #async_exec for the differences between the two API variants.
1419
+ * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1511
1420
  */
1512
1421
  static VALUE
1513
1422
  pgconn_describe_portal(self, stmt_name)
@@ -1515,15 +1424,15 @@ pgconn_describe_portal(self, stmt_name)
1515
1424
  {
1516
1425
  PGresult *result;
1517
1426
  VALUE rb_pgresult;
1518
- PGconn *conn = pg_get_pgconn(self);
1427
+ t_pg_connection *this = pg_get_connection_safe( self );
1519
1428
  const char *stmt;
1520
1429
  if(NIL_P(stmt_name)) {
1521
1430
  stmt = NULL;
1522
1431
  }
1523
1432
  else {
1524
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1433
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1525
1434
  }
1526
- result = gvl_PQdescribePortal(conn, stmt);
1435
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1527
1436
  rb_pgresult = pg_new_result(result, self);
1528
1437
  pg_result_check(rb_pgresult);
1529
1438
  return rb_pgresult;
@@ -1570,13 +1479,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1570
1479
  * Consider using exec_params, which avoids the need for passing values
1571
1480
  * inside of SQL commands.
1572
1481
  *
1573
- * Encoding of escaped string will be equal to client encoding of connection.
1482
+ * Character encoding of escaped string will be equal to client encoding of connection.
1574
1483
  *
1575
1484
  * NOTE: This class version of this method can only be used safely in client
1576
1485
  * programs that use a single PostgreSQL connection at a time (in this case it can
1577
1486
  * find out what it needs to know "behind the scenes"). It might give the wrong
1578
1487
  * results if used in programs that use multiple database connections; use the
1579
1488
  * same method on the connection object in such cases.
1489
+ *
1490
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1580
1491
  */
1581
1492
  static VALUE
1582
1493
  pgconn_s_escape(VALUE self, VALUE string)
@@ -1588,7 +1499,7 @@ pgconn_s_escape(VALUE self, VALUE string)
1588
1499
  int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1589
1500
 
1590
1501
  StringValueCStr(string);
1591
- enc_idx = ENCODING_GET( singleton ? string : self );
1502
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1592
1503
  if( ENCODING_GET(string) != enc_idx ){
1593
1504
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1594
1505
  }
@@ -1605,7 +1516,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1605
1516
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1606
1517
  }
1607
1518
  rb_str_set_len(result, size);
1608
- OBJ_INFECT(result, string);
1609
1519
 
1610
1520
  return result;
1611
1521
  }
@@ -1651,7 +1561,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1651
1561
  }
1652
1562
 
1653
1563
  ret = rb_str_new((char*)to, to_len - 1);
1654
- OBJ_INFECT(ret, str);
1655
1564
  PQfreemem(to);
1656
1565
  return ret;
1657
1566
  }
@@ -1681,7 +1590,6 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1681
1590
  to = PQunescapeBytea(from, &to_len);
1682
1591
 
1683
1592
  ret = rb_str_new((char*)to, to_len);
1684
- OBJ_INFECT(ret, str);
1685
1593
  PQfreemem(to);
1686
1594
  return ret;
1687
1595
  }
@@ -1692,33 +1600,32 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1692
1600
  *
1693
1601
  * Escape an arbitrary String +str+ as a literal.
1694
1602
  *
1695
- * Available since PostgreSQL-9.0
1603
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1696
1604
  */
1697
1605
  static VALUE
1698
1606
  pgconn_escape_literal(VALUE self, VALUE string)
1699
1607
  {
1700
- PGconn *conn = pg_get_pgconn(self);
1608
+ t_pg_connection *this = pg_get_connection_safe( self );
1701
1609
  char *escaped = NULL;
1702
1610
  VALUE error;
1703
1611
  VALUE result = Qnil;
1704
- int enc_idx = ENCODING_GET(self);
1612
+ int enc_idx = this->enc_idx;
1705
1613
 
1706
1614
  StringValueCStr(string);
1707
1615
  if( ENCODING_GET(string) != enc_idx ){
1708
1616
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1709
1617
  }
1710
1618
 
1711
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1619
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1712
1620
  if (escaped == NULL)
1713
1621
  {
1714
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1622
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1715
1623
  rb_iv_set(error, "@connection", self);
1716
1624
  rb_exc_raise(error);
1717
1625
  return Qnil;
1718
1626
  }
1719
1627
  result = rb_str_new2(escaped);
1720
1628
  PQfreemem(escaped);
1721
- OBJ_INFECT(result, string);
1722
1629
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1723
1630
 
1724
1631
  return result;
@@ -1733,34 +1640,31 @@ pgconn_escape_literal(VALUE self, VALUE string)
1733
1640
  * This method does the same as #quote_ident with a String argument,
1734
1641
  * but it doesn't support an Array argument and it makes use of libpq
1735
1642
  * to process the string.
1736
- *
1737
- * Available since PostgreSQL-9.0
1738
1643
  */
1739
1644
  static VALUE
1740
1645
  pgconn_escape_identifier(VALUE self, VALUE string)
1741
1646
  {
1742
- PGconn *conn = pg_get_pgconn(self);
1647
+ t_pg_connection *this = pg_get_connection_safe( self );
1743
1648
  char *escaped = NULL;
1744
1649
  VALUE error;
1745
1650
  VALUE result = Qnil;
1746
- int enc_idx = ENCODING_GET(self);
1651
+ int enc_idx = this->enc_idx;
1747
1652
 
1748
1653
  StringValueCStr(string);
1749
1654
  if( ENCODING_GET(string) != enc_idx ){
1750
1655
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1751
1656
  }
1752
1657
 
1753
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1658
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1754
1659
  if (escaped == NULL)
1755
1660
  {
1756
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1661
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1757
1662
  rb_iv_set(error, "@connection", self);
1758
1663
  rb_exc_raise(error);
1759
1664
  return Qnil;
1760
1665
  }
1761
1666
  result = rb_str_new2(escaped);
1762
1667
  PQfreemem(escaped);
1763
- OBJ_INFECT(result, string);
1764
1668
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1765
1669
 
1766
1670
  return result;
@@ -1801,8 +1705,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1801
1705
  * # do something with the received row
1802
1706
  * end
1803
1707
  * end
1804
- *
1805
- * Available since PostgreSQL-9.2
1806
1708
  */
1807
1709
  static VALUE
1808
1710
  pgconn_set_single_row_mode(VALUE self)
@@ -1838,20 +1740,20 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1838
1740
  static VALUE
1839
1741
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1840
1742
  {
1841
- PGconn *conn = pg_get_pgconn(self);
1743
+ t_pg_connection *this = pg_get_connection_safe( self );
1842
1744
  VALUE error;
1843
1745
 
1844
1746
  /* If called with no or nil parameters, use PQexec for compatibility */
1845
1747
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1846
- if(gvl_PQsendQuery(conn, pg_cstr_enc(argv[0], ENCODING_GET(self))) == 0) {
1847
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1748
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1749
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1848
1750
  rb_iv_set(error, "@connection", self);
1849
1751
  rb_exc_raise(error);
1850
1752
  }
1851
1753
  return Qnil;
1852
1754
  }
1853
1755
 
1854
- pg_deprecated(("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
1756
+ pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
1855
1757
 
1856
1758
  /* If called with parameters, and optionally result_format,
1857
1759
  * use PQsendQueryParams
@@ -1890,7 +1792,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1890
1792
  * The optional +result_format+ should be 0 for text results, 1
1891
1793
  * for binary.
1892
1794
  *
1893
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1795
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1894
1796
  * This will type cast the params from various Ruby types before transmission
1895
1797
  * based on the encoders defined by the type map. When a type encoder is used
1896
1798
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -1900,13 +1802,13 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1900
1802
  static VALUE
1901
1803
  pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1902
1804
  {
1903
- PGconn *conn = pg_get_pgconn(self);
1805
+ t_pg_connection *this = pg_get_connection_safe( self );
1904
1806
  int result;
1905
1807
  VALUE command, in_res_fmt;
1906
1808
  VALUE error;
1907
1809
  int nParams;
1908
1810
  int resultFormat;
1909
- struct query_params_data paramsData = { ENCODING_GET(self) };
1811
+ struct query_params_data paramsData = { this->enc_idx };
1910
1812
 
1911
1813
  rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1912
1814
  paramsData.with_types = 1;
@@ -1915,13 +1817,13 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1915
1817
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1916
1818
  nParams = alloc_query_params( &paramsData );
1917
1819
 
1918
- result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1820
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1919
1821
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1920
1822
 
1921
1823
  free_query_params( &paramsData );
1922
1824
 
1923
1825
  if(result == 0) {
1924
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1826
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1925
1827
  rb_iv_set(error, "@connection", self);
1926
1828
  rb_exc_raise(error);
1927
1829
  }
@@ -1951,7 +1853,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1951
1853
  static VALUE
1952
1854
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1953
1855
  {
1954
- PGconn *conn = pg_get_pgconn(self);
1856
+ t_pg_connection *this = pg_get_connection_safe( self );
1955
1857
  int result;
1956
1858
  VALUE name, command, in_paramtypes;
1957
1859
  VALUE param;
@@ -1961,7 +1863,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1961
1863
  Oid *paramTypes = NULL;
1962
1864
  const char *name_cstr;
1963
1865
  const char *command_cstr;
1964
- int enc_idx = ENCODING_GET(self);
1866
+ int enc_idx = this->enc_idx;
1965
1867
 
1966
1868
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1967
1869
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1979,12 +1881,12 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1979
1881
  paramTypes[i] = NUM2UINT(param);
1980
1882
  }
1981
1883
  }
1982
- result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1884
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1983
1885
 
1984
1886
  xfree(paramTypes);
1985
1887
 
1986
1888
  if(result == 0) {
1987
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1889
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1988
1890
  rb_iv_set(error, "@connection", self);
1989
1891
  rb_exc_raise(error);
1990
1892
  }
@@ -2016,7 +1918,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2016
1918
  * The optional +result_format+ should be 0 for text results, 1
2017
1919
  * for binary.
2018
1920
  *
2019
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1921
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
2020
1922
  * This will type cast the params from various Ruby types before transmission
2021
1923
  * based on the encoders defined by the type map. When a type encoder is used
2022
1924
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -2026,13 +1928,13 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2026
1928
  static VALUE
2027
1929
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2028
1930
  {
2029
- PGconn *conn = pg_get_pgconn(self);
1931
+ t_pg_connection *this = pg_get_connection_safe( self );
2030
1932
  int result;
2031
1933
  VALUE name, in_res_fmt;
2032
1934
  VALUE error;
2033
1935
  int nParams;
2034
1936
  int resultFormat;
2035
- struct query_params_data paramsData = { ENCODING_GET(self) };
1937
+ struct query_params_data paramsData = { this->enc_idx };
2036
1938
 
2037
1939
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
2038
1940
  paramsData.with_types = 0;
@@ -2046,14 +1948,14 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2046
1948
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
2047
1949
  nParams = alloc_query_params( &paramsData );
2048
1950
 
2049
- result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1951
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2050
1952
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
2051
1953
  resultFormat);
2052
1954
 
2053
1955
  free_query_params( &paramsData );
2054
1956
 
2055
1957
  if(result == 0) {
2056
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1958
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2057
1959
  rb_iv_set(error, "@connection", self);
2058
1960
  rb_exc_raise(error);
2059
1961
  }
@@ -2071,10 +1973,10 @@ static VALUE
2071
1973
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2072
1974
  {
2073
1975
  VALUE error;
2074
- PGconn *conn = pg_get_pgconn(self);
1976
+ t_pg_connection *this = pg_get_connection_safe( self );
2075
1977
  /* returns 0 on failure */
2076
- if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
2077
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1978
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
1979
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2078
1980
  rb_iv_set(error, "@connection", self);
2079
1981
  rb_exc_raise(error);
2080
1982
  }
@@ -2093,10 +1995,10 @@ static VALUE
2093
1995
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2094
1996
  {
2095
1997
  VALUE error;
2096
- PGconn *conn = pg_get_pgconn(self);
1998
+ t_pg_connection *this = pg_get_connection_safe( self );
2097
1999
  /* returns 0 on failure */
2098
- if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2099
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2000
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2001
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2100
2002
  rb_iv_set(error, "@connection", self);
2101
2003
  rb_exc_raise(error);
2102
2004
  }
@@ -2297,7 +2199,7 @@ pgconn_cancel(VALUE self)
2297
2199
  static VALUE
2298
2200
  pgconn_notifies(VALUE self)
2299
2201
  {
2300
- PGconn* conn = pg_get_pgconn(self);
2202
+ t_pg_connection *this = pg_get_connection_safe( self );
2301
2203
  PGnotify *notification;
2302
2204
  VALUE hash;
2303
2205
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2307,17 +2209,17 @@ pgconn_notifies(VALUE self)
2307
2209
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2308
2210
  sym_extra = ID2SYM(rb_intern("extra"));
2309
2211
 
2310
- notification = gvl_PQnotifies(conn);
2212
+ notification = gvl_PQnotifies(this->pgconn);
2311
2213
  if (notification == NULL) {
2312
2214
  return Qnil;
2313
2215
  }
2314
2216
 
2315
2217
  hash = rb_hash_new();
2316
- relname = rb_tainted_str_new2(notification->relname);
2218
+ relname = rb_str_new2(notification->relname);
2317
2219
  be_pid = INT2NUM(notification->be_pid);
2318
- extra = rb_tainted_str_new2(notification->extra);
2319
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2320
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2220
+ extra = rb_str_new2(notification->extra);
2221
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2222
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2321
2223
 
2322
2224
  rb_hash_aset(hash, sym_relname, relname);
2323
2225
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2337,15 +2239,18 @@ pgconn_notifies(VALUE self)
2337
2239
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2338
2240
 
2339
2241
  static void *
2340
- wait_socket_readable( t_pg_connection *this, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2242
+ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2341
2243
  {
2342
- PGconn *conn = this->pgconn;
2244
+ int sd = PQsocket( conn );
2343
2245
  void *retval;
2344
2246
  struct timeval aborttime={0,0}, currtime, waittime;
2345
2247
  DWORD timeout_milisec = INFINITE;
2346
2248
  DWORD wait_ret;
2347
2249
  WSAEVENT hEvent;
2348
2250
 
2251
+ if ( sd < 0 )
2252
+ rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2253
+
2349
2254
  hEvent = WSACreateEvent();
2350
2255
 
2351
2256
  /* Check for connection errors (PQisBusy is true on connection errors) */
@@ -2360,7 +2265,7 @@ wait_socket_readable( t_pg_connection *this, struct timeval *ptimeout, void *(*i
2360
2265
  }
2361
2266
 
2362
2267
  while ( !(retval=is_readable(conn)) ) {
2363
- if ( WSAEventSelect(this->socket, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2268
+ if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2364
2269
  WSACloseEvent( hEvent );
2365
2270
  rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2366
2271
  }
@@ -2412,13 +2317,16 @@ wait_socket_readable( t_pg_connection *this, struct timeval *ptimeout, void *(*i
2412
2317
  /* non Win32 */
2413
2318
 
2414
2319
  static void *
2415
- wait_socket_readable( t_pg_connection *this, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2320
+ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2416
2321
  {
2417
- PGconn *conn = this->pgconn;
2322
+ int sd = PQsocket( conn );
2418
2323
  int ret;
2419
2324
  void *retval;
2420
2325
  struct timeval aborttime={0,0}, currtime, waittime;
2421
2326
 
2327
+ if ( sd < 0 )
2328
+ rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2329
+
2422
2330
  /* Check for connection errors (PQisBusy is true on connection errors) */
2423
2331
  if ( PQconsumeInput(conn) == 0 )
2424
2332
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
@@ -2437,7 +2345,7 @@ wait_socket_readable( t_pg_connection *this, struct timeval *ptimeout, void *(*i
2437
2345
  /* Is the given timeout valid? */
2438
2346
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2439
2347
  /* Wait for the socket to become readable before checking again */
2440
- ret = rb_wait_for_single_fd( this->socket, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2348
+ ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2441
2349
  } else {
2442
2350
  ret = 0;
2443
2351
  }
@@ -2500,17 +2408,17 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2500
2408
  ptimeout = &timeout;
2501
2409
  }
2502
2410
 
2503
- pnotification = (PGnotify*) wait_socket_readable( this, ptimeout, notify_readable);
2411
+ pnotification = (PGnotify*) wait_socket_readable( this->pgconn, ptimeout, notify_readable);
2504
2412
 
2505
2413
  /* Return nil if the select timed out */
2506
2414
  if ( !pnotification ) return Qnil;
2507
2415
 
2508
- relname = rb_tainted_str_new2( pnotification->relname );
2509
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2416
+ relname = rb_str_new2( pnotification->relname );
2417
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2510
2418
  be_pid = INT2NUM( pnotification->be_pid );
2511
2419
  if ( *pnotification->extra ) {
2512
- extra = rb_tainted_str_new2( pnotification->extra );
2513
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2420
+ extra = rb_str_new2( pnotification->extra );
2421
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2514
2422
  }
2515
2423
  PQfreemem( pnotification );
2516
2424
 
@@ -2570,7 +2478,7 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2570
2478
 
2571
2479
  if( p_coder ){
2572
2480
  t_pg_coder_enc_func enc_func;
2573
- int enc_idx = ENCODING_GET(self);
2481
+ int enc_idx = this->enc_idx;
2574
2482
 
2575
2483
  enc_func = pg_coder_enc_func( p_coder );
2576
2484
  len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
@@ -2620,16 +2528,16 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2620
2528
  VALUE error;
2621
2529
  int ret;
2622
2530
  const char *error_message = NULL;
2623
- PGconn *conn = pg_get_pgconn(self);
2531
+ t_pg_connection *this = pg_get_connection_safe( self );
2624
2532
 
2625
2533
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2626
2534
  error_message = NULL;
2627
2535
  else
2628
- error_message = pg_cstr_enc(str, ENCODING_GET(self));
2536
+ error_message = pg_cstr_enc(str, this->enc_idx);
2629
2537
 
2630
- ret = gvl_PQputCopyEnd(conn, error_message);
2538
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2631
2539
  if(ret == -1) {
2632
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2540
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2633
2541
  rb_iv_set(error, "@connection", self);
2634
2542
  rb_exc_raise(error);
2635
2543
  }
@@ -2695,9 +2603,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2695
2603
 
2696
2604
  if( p_coder ){
2697
2605
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2698
- result = dec_func( p_coder, buffer, ret, 0, 0, ENCODING_GET(self) );
2606
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2699
2607
  } else {
2700
- result = rb_tainted_str_new(buffer, ret);
2608
+ result = rb_str_new(buffer, ret);
2701
2609
  }
2702
2610
 
2703
2611
  PQfreemem(buffer);
@@ -2710,9 +2618,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2710
2618
  *
2711
2619
  * Sets connection's verbosity to _verbosity_ and returns
2712
2620
  * the previous setting. Available settings are:
2621
+ *
2713
2622
  * * PQERRORS_TERSE
2714
2623
  * * PQERRORS_DEFAULT
2715
2624
  * * PQERRORS_VERBOSE
2625
+ * * PQERRORS_SQLSTATE
2626
+ *
2627
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2628
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2629
+ *
2630
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2716
2631
  */
2717
2632
  static VALUE
2718
2633
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2722,6 +2637,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2722
2637
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2723
2638
  }
2724
2639
 
2640
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2641
+ /*
2642
+ * call-seq:
2643
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2644
+ *
2645
+ * Sets connection's context display mode to _context_visibility_ and returns
2646
+ * the previous setting. Available settings are:
2647
+ * * PQSHOW_CONTEXT_NEVER
2648
+ * * PQSHOW_CONTEXT_ERRORS
2649
+ * * PQSHOW_CONTEXT_ALWAYS
2650
+ *
2651
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2652
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2653
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2654
+ *
2655
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2656
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2657
+ *
2658
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2659
+ *
2660
+ * Available since PostgreSQL-9.6
2661
+ */
2662
+ static VALUE
2663
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2664
+ {
2665
+ PGconn *conn = pg_get_pgconn(self);
2666
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2667
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2668
+ }
2669
+ #endif
2670
+
2725
2671
  /*
2726
2672
  * call-seq:
2727
2673
  * conn.trace( stream ) -> nil
@@ -2740,7 +2686,7 @@ pgconn_trace(VALUE self, VALUE stream)
2740
2686
  VALUE new_file;
2741
2687
  t_pg_connection *this = pg_get_connection_safe( self );
2742
2688
 
2743
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2689
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2744
2690
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2745
2691
 
2746
2692
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2873,8 +2819,8 @@ notice_processor_proxy(void *arg, const char *message)
2873
2819
  t_pg_connection *this = pg_get_connection( self );
2874
2820
 
2875
2821
  if (this->notice_receiver != Qnil) {
2876
- VALUE message_str = rb_tainted_str_new2(message);
2877
- PG_ENCODING_SET_NOCHECK( message_str, ENCODING_GET(self) );
2822
+ VALUE message_str = rb_str_new2(message);
2823
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2878
2824
  rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2879
2825
  }
2880
2826
  return;
@@ -2932,7 +2878,7 @@ static VALUE
2932
2878
  pgconn_get_client_encoding(VALUE self)
2933
2879
  {
2934
2880
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2935
- return rb_tainted_str_new2(encoding);
2881
+ return rb_str_new2(encoding);
2936
2882
  }
2937
2883
 
2938
2884
 
@@ -3044,14 +2990,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3044
2990
  int enc_idx;
3045
2991
 
3046
2992
  if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3047
- enc_idx = ENCODING_GET( self );
2993
+ enc_idx = pg_get_connection(self)->enc_idx;
3048
2994
  }else{
3049
2995
  enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3050
2996
  }
3051
2997
  pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3052
2998
 
3053
- OBJ_INFECT(ret, str_or_array);
3054
-
3055
2999
  return ret;
3056
3000
  }
3057
3001
 
@@ -3078,7 +3022,7 @@ get_result_readable(PGconn *conn)
3078
3022
  */
3079
3023
  static VALUE
3080
3024
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
3081
- t_pg_connection *this = pg_get_connection_safe( self );
3025
+ PGconn *conn = pg_get_pgconn( self );
3082
3026
 
3083
3027
  struct timeval timeout;
3084
3028
  struct timeval *ptimeout = NULL;
@@ -3093,7 +3037,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3093
3037
  ptimeout = &timeout;
3094
3038
  }
3095
3039
 
3096
- ret = wait_socket_readable( this, ptimeout, get_result_readable);
3040
+ ret = wait_socket_readable( conn, ptimeout, get_result_readable);
3097
3041
 
3098
3042
  if( !ret )
3099
3043
  return Qfalse;
@@ -3176,19 +3120,30 @@ pgconn_discard_results(VALUE self)
3176
3120
 
3177
3121
  /*
3178
3122
  * call-seq:
3179
- * conn.async_exec(sql) -> PG::Result
3180
- * conn.async_exec(sql) {|pg_result| block }
3123
+ * conn.exec(sql) -> PG::Result
3124
+ * conn.exec(sql) {|pg_result| block }
3181
3125
  *
3182
- * This function has the same behavior as #sync_exec,
3183
- * but is implemented using the asynchronous command
3184
- * processing API of libpq.
3126
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3127
+ * On success, it returns a PG::Result instance with all result rows and columns.
3128
+ * On failure, it raises a PG::Error.
3185
3129
  *
3186
- * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
3187
- * However #async_exec has two advantages:
3130
+ * For backward compatibility, if you pass more than one parameter to this method,
3131
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3132
+ * argument placeholders are used.
3188
3133
  *
3189
- * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
3190
- * 2. Ruby VM gets notified about IO blocked operations.
3191
- * It can therefore schedule thing like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
3134
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3135
+ * and the PG::Result object will automatically be cleared when the block terminates.
3136
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3137
+ *
3138
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3139
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3140
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3141
+ * Both methods ensure that other threads can process while waiting for the server to
3142
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3143
+ * This is most notably visible by a delayed reaction to Control+C.
3144
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3145
+ *
3146
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3192
3147
  */
3193
3148
  static VALUE
3194
3149
  pgconn_async_exec(int argc, VALUE *argv, VALUE self)
@@ -3209,11 +3164,53 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3209
3164
 
3210
3165
  /*
3211
3166
  * call-seq:
3212
- * conn.async_exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3213
- * conn.async_exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3167
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3168
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3214
3169
  *
3215
- * This function has the same behavior as #sync_exec_params, but is implemented using the asynchronous command processing API of libpq.
3216
- * See #async_exec for the differences between the two API variants.
3170
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3171
+ * for parameters.
3172
+ *
3173
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3174
+ *
3175
+ * +params+ is an array of the bind parameters for the SQL query.
3176
+ * Each element of the +params+ array may be either:
3177
+ * a hash of the form:
3178
+ * {:value => String (value of bind parameter)
3179
+ * :type => Integer (oid of type of bind parameter)
3180
+ * :format => Integer (0 for text, 1 for binary)
3181
+ * }
3182
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3183
+ * { :value => <string value>, :type => 0, :format => 0 }
3184
+ *
3185
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3186
+ * inside the SQL query. The 0th element of the +params+ array is bound
3187
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3188
+ *
3189
+ * If the types are not specified, they will be inferred by PostgreSQL.
3190
+ * Instead of specifying type oids, it's recommended to simply add
3191
+ * explicit casts in the query to ensure that the right type is used.
3192
+ *
3193
+ * For example: "SELECT $1::int"
3194
+ *
3195
+ * The optional +result_format+ should be 0 for text results, 1
3196
+ * for binary.
3197
+ *
3198
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3199
+ * This will type cast the params from various Ruby types before transmission
3200
+ * based on the encoders defined by the type map. When a type encoder is used
3201
+ * the format and oid of a given bind parameter are retrieved from the encoder
3202
+ * instead out of the hash form described above.
3203
+ *
3204
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3205
+ * and the PG::Result object will automatically be cleared when the block terminates.
3206
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3207
+ *
3208
+ * The primary advantage of #exec_params over #exec is that parameter values can be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping.
3209
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3210
+ * (There can be semicolons in it, but not more than one nonempty command.)
3211
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3212
+ *
3213
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3217
3214
  */
3218
3215
  static VALUE
3219
3216
  pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
@@ -3223,7 +3220,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3223
3220
  pgconn_discard_results( self );
3224
3221
  /* If called with no or nil parameters, use PQsendQuery for compatibility */
3225
3222
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
3226
- pg_deprecated(("forwarding async_exec_params to async_exec is deprecated"));
3223
+ pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
3227
3224
  pgconn_send_query( argc, argv, self );
3228
3225
  } else {
3229
3226
  pgconn_send_query_params( argc, argv, self );
@@ -3240,10 +3237,25 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3240
3237
 
3241
3238
  /*
3242
3239
  * call-seq:
3243
- * conn.async_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3240
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3244
3241
  *
3245
- * This function has the same behavior as #sync_prepare, but is implemented using the asynchronous command processing API of libpq.
3246
- * See #async_exec for the differences between the two API variants.
3242
+ * Prepares statement _sql_ with name _name_ to be executed later.
3243
+ * Returns a PG::Result instance on success.
3244
+ * On failure, it raises a PG::Error.
3245
+ *
3246
+ * +param_types+ is an optional parameter to specify the Oids of the
3247
+ * types of the parameters.
3248
+ *
3249
+ * If the types are not specified, they will be inferred by PostgreSQL.
3250
+ * Instead of specifying type oids, it's recommended to simply add
3251
+ * explicit casts in the query to ensure that the right type is used.
3252
+ *
3253
+ * For example: "SELECT $1::int"
3254
+ *
3255
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3256
+ * inside the SQL query.
3257
+ *
3258
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3247
3259
  */
3248
3260
  static VALUE
3249
3261
  pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
@@ -3264,11 +3276,40 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3264
3276
 
3265
3277
  /*
3266
3278
  * call-seq:
3267
- * conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3268
- * conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3279
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3280
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3269
3281
  *
3270
- * This function has the same behavior as #sync_exec_prepared, but is implemented using the asynchronous command processing API of libpq.
3271
- * See #async_exec for the differences between the two API variants.
3282
+ * Execute prepared named statement specified by _statement_name_.
3283
+ * Returns a PG::Result instance on success.
3284
+ * On failure, it raises a PG::Error.
3285
+ *
3286
+ * +params+ is an array of the optional bind parameters for the
3287
+ * SQL query. Each element of the +params+ array may be either:
3288
+ * a hash of the form:
3289
+ * {:value => String (value of bind parameter)
3290
+ * :format => Integer (0 for text, 1 for binary)
3291
+ * }
3292
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3293
+ * { :value => <string value>, :format => 0 }
3294
+ *
3295
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3296
+ * inside the SQL query. The 0th element of the +params+ array is bound
3297
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3298
+ *
3299
+ * The optional +result_format+ should be 0 for text results, 1
3300
+ * for binary.
3301
+ *
3302
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3303
+ * This will type cast the params from various Ruby types before transmission
3304
+ * based on the encoders defined by the type map. When a type encoder is used
3305
+ * the format and oid of a given bind parameter are retrieved from the encoder
3306
+ * instead out of the hash form described above.
3307
+ *
3308
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3309
+ * and the PG::Result object will automatically be cleared when the block terminates.
3310
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3311
+ *
3312
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3272
3313
  */
3273
3314
  static VALUE
3274
3315
  pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
@@ -3289,10 +3330,11 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3289
3330
 
3290
3331
  /*
3291
3332
  * call-seq:
3292
- * conn.async_describe_portal( portal_name ) -> PG::Result
3333
+ * conn.describe_portal( portal_name ) -> PG::Result
3293
3334
  *
3294
- * This function has the same behavior as #sync_describe_portal, but is implemented using the asynchronous command processing API of libpq.
3295
- * See #async_exec for the differences between the two API variants.
3335
+ * Retrieve information about the portal _portal_name_.
3336
+ *
3337
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3296
3338
  */
3297
3339
  static VALUE
3298
3340
  pgconn_async_describe_portal(VALUE self, VALUE portal)
@@ -3313,10 +3355,11 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3313
3355
 
3314
3356
  /*
3315
3357
  * call-seq:
3316
- * conn.async_describe_prepared( statement_name ) -> PG::Result
3358
+ * conn.describe_prepared( statement_name ) -> PG::Result
3317
3359
  *
3318
- * This function has the same behavior as #sync_describe_prepared, but is implemented using the asynchronous command processing API of libpq.
3319
- * See #async_exec for the differences between the two API variants.
3360
+ * Retrieve information about the prepared statement _statement_name_.
3361
+ *
3362
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3320
3363
  */
3321
3364
  static VALUE
3322
3365
  pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
@@ -3340,7 +3383,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3340
3383
  * call-seq:
3341
3384
  * conn.ssl_in_use? -> Boolean
3342
3385
  *
3343
- * Returns +true+ if the connection uses SSL, +false+ if not.
3386
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3344
3387
  *
3345
3388
  * Available since PostgreSQL-9.5
3346
3389
  */
@@ -3374,7 +3417,7 @@ pgconn_ssl_in_use(VALUE self)
3374
3417
  * If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
3375
3418
  *
3376
3419
  *
3377
- * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3420
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3378
3421
  *
3379
3422
  * Available since PostgreSQL-9.5
3380
3423
  */
@@ -3602,7 +3645,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3602
3645
  return Qnil;
3603
3646
  }
3604
3647
 
3605
- str = rb_tainted_str_new(buffer, ret);
3648
+ str = rb_str_new(buffer, ret);
3606
3649
  xfree(buffer);
3607
3650
 
3608
3651
  return str;
@@ -3706,12 +3749,15 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3706
3749
  }
3707
3750
 
3708
3751
 
3709
- void
3752
+ static void
3710
3753
  pgconn_set_internal_encoding_index( VALUE self )
3711
3754
  {
3712
- PGconn *conn = pg_get_pgconn(self);
3713
- rb_encoding *enc = pg_conn_enc_get( conn );
3714
- PG_ENCODING_SET_NOCHECK( self, rb_enc_to_index(enc));
3755
+ int enc_idx;
3756
+ t_pg_connection *this = pg_get_connection_safe( self );
3757
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
3758
+ enc_idx = rb_enc_to_index(enc);
3759
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
3760
+ this->enc_idx = enc_idx;
3715
3761
  }
3716
3762
 
3717
3763
  /*
@@ -3754,7 +3800,6 @@ static VALUE pgconn_external_encoding(VALUE self);
3754
3800
  static VALUE
3755
3801
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3756
3802
  {
3757
- VALUE enc_inspect;
3758
3803
  if (NIL_P(enc)) {
3759
3804
  pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3760
3805
  return enc;
@@ -3775,11 +3820,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3775
3820
  pgconn_set_internal_encoding_index( self );
3776
3821
  return enc;
3777
3822
  }
3778
-
3779
- enc_inspect = rb_inspect(enc);
3780
- rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
3781
-
3782
- return Qnil;
3783
3823
  }
3784
3824
 
3785
3825
 
@@ -3798,14 +3838,9 @@ pgconn_external_encoding(VALUE self)
3798
3838
  rb_encoding *enc = NULL;
3799
3839
  const char *pg_encname = NULL;
3800
3840
 
3801
- /* Use cached value if found */
3802
- if ( RTEST(this->external_encoding) ) return this->external_encoding;
3803
-
3804
3841
  pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3805
3842
  enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3806
- this->external_encoding = rb_enc_from_encoding( enc );
3807
-
3808
- return this->external_encoding;
3843
+ return rb_enc_from_encoding( enc );
3809
3844
  }
3810
3845
 
3811
3846
 
@@ -3823,9 +3858,10 @@ pgconn_set_client_encoding_async1( VALUE args )
3823
3858
 
3824
3859
 
3825
3860
  static VALUE
3826
- pgconn_set_client_encoding_async2( VALUE arg )
3861
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3827
3862
  {
3828
3863
  UNUSED(arg);
3864
+ UNUSED(ex);
3829
3865
  return 1;
3830
3866
  }
3831
3867
 
@@ -4047,16 +4083,54 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
4047
4083
 
4048
4084
  /*
4049
4085
  * call-seq:
4050
- * res.guess_result_memsize = enabled
4086
+ * conn.field_name_type = Symbol
4087
+ *
4088
+ * Set default type of field names of results retrieved by this connection.
4089
+ * It can be set to one of:
4090
+ * * +:string+ to use String based field names
4091
+ * * +:symbol+ to use Symbol based field names
4092
+ *
4093
+ * The default is +:string+ .
4094
+ *
4095
+ * Settings the type of field names affects only future results.
4096
+ *
4097
+ * See further description at PG::Result#field_name_type=
4051
4098
  *
4052
- * This method is for testing only and will probably be removed in the future.
4053
4099
  */
4054
4100
  static VALUE
4055
- pgconn_guess_result_memsize_set(VALUE self, VALUE enable)
4101
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4056
4102
  {
4057
4103
  t_pg_connection *this = pg_get_connection( self );
4058
- this->guess_result_memsize = RTEST(enable);
4059
- return enable;
4104
+
4105
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4106
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4107
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4108
+ else if ( sym == sym_string );
4109
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4110
+
4111
+ return sym;
4112
+ }
4113
+
4114
+ /*
4115
+ * call-seq:
4116
+ * conn.field_name_type -> Symbol
4117
+ *
4118
+ * Get type of field names.
4119
+ *
4120
+ * See description at #field_name_type=
4121
+ */
4122
+ static VALUE
4123
+ pgconn_field_name_type_get(VALUE self)
4124
+ {
4125
+ t_pg_connection *this = pg_get_connection( self );
4126
+
4127
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4128
+ return sym_symbol;
4129
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4130
+ return sym_static_symbol;
4131
+ } else {
4132
+ return sym_string;
4133
+ }
4060
4134
  }
4061
4135
 
4062
4136
 
@@ -4070,8 +4144,13 @@ init_pg_connection()
4070
4144
  sym_type = ID2SYM(rb_intern("type"));
4071
4145
  sym_format = ID2SYM(rb_intern("format"));
4072
4146
  sym_value = ID2SYM(rb_intern("value"));
4147
+ sym_string = ID2SYM(rb_intern("string"));
4148
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4149
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
4073
4150
 
4074
4151
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4152
+ /* Help rdoc to known the Constants module */
4153
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
4075
4154
  rb_include_module(rb_cPGconn, rb_mPGconstants);
4076
4155
 
4077
4156
  /****** PG::Connection CLASS METHODS ******/
@@ -4132,6 +4211,22 @@ init_pg_connection()
4132
4211
  rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
4133
4212
  rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
4134
4213
  rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
4214
+
4215
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4216
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4217
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4218
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4219
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4220
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4221
+
4222
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4223
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4224
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4225
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4226
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4227
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4228
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4229
+
4135
4230
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
4136
4231
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4137
4232
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
@@ -4144,17 +4239,10 @@ init_pg_connection()
4144
4239
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4145
4240
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4146
4241
  rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
4147
- rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
4148
- rb_define_method(rb_cPGconn, "async_exec_params", pgconn_async_exec_params, -1);
4149
- rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4150
4242
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
4151
- rb_define_method(rb_cPGconn, "async_prepare", pgconn_async_prepare, -1);
4152
4243
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4153
- rb_define_method(rb_cPGconn, "async_exec_prepared", pgconn_async_exec_prepared, -1);
4154
4244
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4155
- rb_define_method(rb_cPGconn, "async_describe_prepared", pgconn_async_describe_prepared, 1);
4156
4245
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4157
- rb_define_method(rb_cPGconn, "async_describe_portal", pgconn_async_describe_portal, 1);
4158
4246
  rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4159
4247
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4160
4248
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
@@ -4177,9 +4265,11 @@ init_pg_connection()
4177
4265
 
4178
4266
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4179
4267
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4268
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4269
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4270
+ #endif
4180
4271
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4181
4272
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
4182
- rb_define_method(rb_cPGconn, "guess_result_memsize=", pgconn_guess_result_memsize_set, 1);
4183
4273
 
4184
4274
  /****** PG::Connection INSTANCE METHODS: Notice Processing ******/
4185
4275
  rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
@@ -4246,5 +4336,7 @@ init_pg_connection()
4246
4336
  rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4247
4337
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4248
4338
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4249
- }
4250
4339
 
4340
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4341
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
4342
+ }