pg 0.19.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/ChangeLog +218 -1
  4. data/History.rdoc +106 -0
  5. data/Manifest.txt +5 -18
  6. data/README.rdoc +15 -5
  7. data/Rakefile +8 -9
  8. data/Rakefile.cross +19 -22
  9. data/ext/errorcodes.def +17 -0
  10. data/ext/errorcodes.rb +1 -1
  11. data/ext/errorcodes.txt +11 -1
  12. data/ext/extconf.rb +14 -32
  13. data/ext/gvl_wrappers.c +4 -0
  14. data/ext/gvl_wrappers.h +23 -39
  15. data/ext/pg.c +19 -48
  16. data/ext/pg.h +46 -81
  17. data/ext/pg_binary_decoder.c +69 -6
  18. data/ext/pg_coder.c +53 -4
  19. data/ext/pg_connection.c +401 -253
  20. data/ext/pg_copy_coder.c +10 -5
  21. data/ext/pg_result.c +359 -131
  22. data/ext/pg_text_decoder.c +597 -37
  23. data/ext/pg_text_encoder.c +6 -7
  24. data/ext/pg_tuple.c +541 -0
  25. data/ext/pg_type_map.c +14 -7
  26. data/ext/util.c +6 -6
  27. data/ext/util.h +2 -2
  28. data/lib/pg/basic_type_mapping.rb +40 -7
  29. data/lib/pg/binary_decoder.rb +22 -0
  30. data/lib/pg/coder.rb +1 -1
  31. data/lib/pg/connection.rb +27 -7
  32. data/lib/pg/constants.rb +1 -1
  33. data/lib/pg/exceptions.rb +1 -1
  34. data/lib/pg/result.rb +6 -5
  35. data/lib/pg/text_decoder.rb +19 -23
  36. data/lib/pg/text_encoder.rb +36 -2
  37. data/lib/pg/tuple.rb +30 -0
  38. data/lib/pg/type_map_by_column.rb +1 -1
  39. data/lib/pg.rb +21 -11
  40. data/spec/helpers.rb +47 -19
  41. data/spec/pg/basic_type_mapping_spec.rb +230 -27
  42. data/spec/pg/connection_spec.rb +402 -275
  43. data/spec/pg/connection_sync_spec.rb +41 -0
  44. data/spec/pg/result_spec.rb +59 -17
  45. data/spec/pg/tuple_spec.rb +280 -0
  46. data/spec/pg/type_map_by_class_spec.rb +2 -2
  47. data/spec/pg/type_map_by_column_spec.rb +1 -1
  48. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  49. data/spec/pg/type_map_by_oid_spec.rb +1 -1
  50. data/spec/pg/type_map_in_ruby_spec.rb +1 -1
  51. data/spec/pg/type_map_spec.rb +1 -1
  52. data/spec/pg/type_spec.rb +184 -12
  53. data/spec/pg_spec.rb +2 -2
  54. data.tar.gz.sig +0 -0
  55. metadata +47 -53
  56. metadata.gz.sig +0 -0
  57. data/sample/array_insert.rb +0 -20
  58. data/sample/async_api.rb +0 -106
  59. data/sample/async_copyto.rb +0 -39
  60. data/sample/async_mixed.rb +0 -56
  61. data/sample/check_conn.rb +0 -21
  62. data/sample/copyfrom.rb +0 -81
  63. data/sample/copyto.rb +0 -19
  64. data/sample/cursor.rb +0 -21
  65. data/sample/disk_usage_report.rb +0 -186
  66. data/sample/issue-119.rb +0 -94
  67. data/sample/losample.rb +0 -69
  68. data/sample/minimal-testcase.rb +0 -17
  69. data/sample/notify_wait.rb +0 -72
  70. data/sample/pg_statistics.rb +0 -294
  71. data/sample/replication_monitor.rb +0 -231
  72. data/sample/test_binary_values.rb +0 -33
  73. data/sample/wal_shipper.rb +0 -434
  74. data/sample/warehouse_partitions.rb +0 -320
@@ -1,9 +1,10 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_binary_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
3
+ * $Id: pg_binary_decoder.c,v 5d166a4d0441 2018/07/29 12:03:00 lars $
4
4
  *
5
5
  */
6
6
 
7
+ #include "ruby/version.h"
7
8
  #include "pg.h"
8
9
  #include "util.h"
9
10
  #ifdef HAVE_INTTYPES_H
@@ -21,7 +22,7 @@ VALUE rb_mPG_BinaryDecoder;
21
22
  *
22
23
  */
23
24
  static VALUE
24
- pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
25
+ pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
25
26
  {
26
27
  if (len < 1) {
27
28
  rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
@@ -37,7 +38,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, i
37
38
  *
38
39
  */
39
40
  static VALUE
40
- pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
41
+ pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
41
42
  {
42
43
  switch( len ){
43
44
  case 2:
@@ -59,7 +60,7 @@ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, i
59
60
  *
60
61
  */
61
62
  static VALUE
62
- pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
63
+ pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
63
64
  {
64
65
  union {
65
66
  float f;
@@ -91,7 +92,7 @@ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int
91
92
  *
92
93
  */
93
94
  VALUE
94
- pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
95
+ pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
95
96
  {
96
97
  VALUE ret;
97
98
  ret = rb_tainted_str_new( val, len );
@@ -106,7 +107,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int
106
107
  *
107
108
  */
108
109
  static VALUE
109
- pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
110
+ pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
110
111
  {
111
112
  t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
112
113
  t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
@@ -130,6 +131,66 @@ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field,
130
131
  return out_value;
131
132
  }
132
133
 
134
+ #define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
135
+ #define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
136
+
137
+ /*
138
+ * Document-class: PG::BinaryDecoder::Timestamp < PG::SimpleDecoder
139
+ *
140
+ * This is a decoder class for conversion of PostgreSQL binary timestamps
141
+ * to Ruby Time objects.
142
+ *
143
+ * The following flags can be used to specify timezone interpretation:
144
+ * * +PG::Coder::TIMESTAMP_DB_UTC+ : Interpret timestamp as UTC time (default)
145
+ * * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Interpret timestamp as local time
146
+ * * +PG::Coder::TIMESTAMP_APP_UTC+ : Return timestamp as UTC time (default)
147
+ * * +PG::Coder::TIMESTAMP_APP_LOCAL+ : Return timestamp as local time
148
+ *
149
+ * Example:
150
+ * deco = PG::BinaryDecoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
151
+ * deco.decode("\0"*8) # => 2000-01-01 01:00:00 +0100
152
+ */
153
+ static VALUE
154
+ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
155
+ {
156
+ int64_t timestamp;
157
+ struct timespec ts;
158
+ VALUE t;
159
+
160
+ if( len != sizeof(timestamp) ){
161
+ rb_raise( rb_eTypeError, "wrong data for timestamp converter in tuple %d field %d length %d", tuple, field, len);
162
+ }
163
+
164
+ timestamp = read_nbo64(val);
165
+
166
+ switch(timestamp){
167
+ case PG_INT64_MAX:
168
+ return rb_str_new2("infinity");
169
+ case PG_INT64_MIN:
170
+ return rb_str_new2("-infinity");
171
+ default:
172
+ /* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
173
+ * Adjust the 30 years difference. */
174
+ ts.tv_sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
175
+ ts.tv_nsec = (timestamp % 1000000) * 1000;
176
+
177
+ #if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T)
178
+ /* Fast path for time conversion */
179
+ t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
180
+ #else
181
+ t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(ts.tv_sec), LL2NUM(ts.tv_nsec / 1000));
182
+ if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
183
+ t = rb_funcall(t, rb_intern("utc"), 0);
184
+ }
185
+ #endif
186
+ if( conv->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
187
+ /* interpret it as local time */
188
+ t = rb_funcall(t, rb_intern("-"), 1, rb_funcall(t, rb_intern("utc_offset"), 0));
189
+ }
190
+ return t;
191
+ }
192
+ }
193
+
133
194
  /*
134
195
  * Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
135
196
  *
@@ -156,6 +217,8 @@ init_pg_binary_decoder()
156
217
  pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
157
218
  /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
158
219
  pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
220
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
221
+ pg_define_coder( "Timestamp", pg_bin_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
159
222
 
160
223
  /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
161
224
  pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
data/ext/pg_coder.c CHANGED
@@ -38,6 +38,7 @@ pg_coder_init_encoder( VALUE self )
38
38
  this->coder_obj = self;
39
39
  this->oid = 0;
40
40
  this->format = 0;
41
+ this->flags = 0;
41
42
  rb_iv_set( self, "@name", Qnil );
42
43
  }
43
44
 
@@ -56,6 +57,7 @@ pg_coder_init_decoder( VALUE self )
56
57
  this->coder_obj = self;
57
58
  this->oid = 0;
58
59
  this->format = 0;
60
+ this->flags = 0;
59
61
  rb_iv_set( self, "@name", Qnil );
60
62
  }
61
63
 
@@ -105,7 +107,7 @@ pg_composite_decoder_allocate( VALUE klass )
105
107
 
106
108
  /*
107
109
  * call-seq:
108
- * coder.encode( value )
110
+ * coder.encode( value [, encoding] )
109
111
  *
110
112
  * Encodes the given Ruby object into string representation, without
111
113
  * sending data to/from the database server.
@@ -192,7 +194,11 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
192
194
  if( NIL_P(argv[0]) )
193
195
  return Qnil;
194
196
 
195
- val = StringValuePtr(argv[0]);
197
+ if( this->format == 0 ){
198
+ val = StringValueCStr(argv[0]);
199
+ }else{
200
+ val = StringValuePtr(argv[0]);
201
+ }
196
202
  if( !this->dec_func ){
197
203
  rb_raise(rb_eRuntimeError, "no decoder function defined");
198
204
  }
@@ -265,6 +271,36 @@ pg_coder_format_get(VALUE self)
265
271
  return INT2NUM(this->format);
266
272
  }
267
273
 
274
+ /*
275
+ * call-seq:
276
+ * coder.flags = Integer
277
+ *
278
+ * Set coder specific bitwise OR-ed flags.
279
+ * See the particular en- or decoder description for available flags.
280
+ *
281
+ * The default is +0+.
282
+ */
283
+ static VALUE
284
+ pg_coder_flags_set(VALUE self, VALUE flags)
285
+ {
286
+ t_pg_coder *this = DATA_PTR(self);
287
+ this->flags = NUM2INT(flags);
288
+ return flags;
289
+ }
290
+
291
+ /*
292
+ * call-seq:
293
+ * coder.flags -> Integer
294
+ *
295
+ * Get current bitwise OR-ed coder flags.
296
+ */
297
+ static VALUE
298
+ pg_coder_flags_get(VALUE self)
299
+ {
300
+ t_pg_coder *this = DATA_PTR(self);
301
+ return INT2NUM(this->flags);
302
+ }
303
+
268
304
  /*
269
305
  * call-seq:
270
306
  * coder.needs_quotation = Boolean
@@ -403,14 +439,14 @@ pg_coder_enc_func(t_pg_coder *this)
403
439
  }
404
440
 
405
441
  static VALUE
406
- pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
442
+ pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
407
443
  {
408
444
  VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
409
445
  return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
410
446
  }
411
447
 
412
448
  static VALUE
413
- pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
449
+ pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
414
450
  {
415
451
  VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
416
452
  return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
@@ -457,6 +493,19 @@ init_pg_coder()
457
493
  rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
458
494
  rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
459
495
  rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
496
+ rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
497
+ rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
498
+
499
+ /* define flags to be used with PG::Coder#flags= */
500
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
501
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
502
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
503
+ rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
504
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
505
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
506
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
507
+ rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
508
+
460
509
  /*
461
510
  * Name of the coder or the corresponding data type.
462
511
  *