pg 0.18.4 → 1.2.3

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