pg 1.1.4 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +0 -6595
  5. data/History.rdoc +63 -0
  6. data/Manifest.txt +3 -2
  7. data/README-Windows.rdoc +4 -4
  8. data/README.ja.rdoc +1 -2
  9. data/README.rdoc +43 -8
  10. data/Rakefile +3 -3
  11. data/Rakefile.cross +6 -3
  12. data/ext/errorcodes.def +64 -0
  13. data/ext/errorcodes.txt +18 -2
  14. data/ext/extconf.rb +6 -6
  15. data/ext/pg.c +132 -95
  16. data/ext/pg.h +20 -18
  17. data/ext/pg_binary_decoder.c +9 -9
  18. data/ext/pg_binary_encoder.c +13 -12
  19. data/ext/pg_coder.c +5 -5
  20. data/ext/pg_connection.c +388 -298
  21. data/ext/pg_copy_coder.c +5 -3
  22. data/ext/pg_record_coder.c +490 -0
  23. data/ext/pg_result.c +269 -123
  24. data/ext/pg_text_decoder.c +14 -8
  25. data/ext/pg_text_encoder.c +180 -48
  26. data/ext/pg_tuple.c +14 -6
  27. data/ext/pg_type_map.c +1 -1
  28. data/ext/pg_type_map_all_strings.c +4 -4
  29. data/ext/pg_type_map_by_class.c +4 -3
  30. data/ext/pg_type_map_by_column.c +7 -6
  31. data/ext/pg_type_map_by_mri_type.c +1 -1
  32. data/ext/pg_type_map_by_oid.c +3 -2
  33. data/ext/pg_type_map_in_ruby.c +1 -1
  34. data/ext/{util.c → pg_util.c} +5 -5
  35. data/ext/{util.h → pg_util.h} +0 -0
  36. data/lib/pg.rb +2 -3
  37. data/lib/pg/basic_type_mapping.rb +79 -16
  38. data/lib/pg/binary_decoder.rb +1 -0
  39. data/lib/pg/coder.rb +22 -1
  40. data/lib/pg/connection.rb +2 -2
  41. data/lib/pg/constants.rb +1 -0
  42. data/lib/pg/exceptions.rb +1 -0
  43. data/lib/pg/result.rb +13 -1
  44. data/lib/pg/text_decoder.rb +2 -3
  45. data/lib/pg/text_encoder.rb +8 -18
  46. data/lib/pg/type_map_by_column.rb +2 -1
  47. data/spec/helpers.rb +10 -8
  48. data/spec/pg/basic_type_mapping_spec.rb +150 -13
  49. data/spec/pg/connection_spec.rb +89 -50
  50. data/spec/pg/result_spec.rb +193 -3
  51. data/spec/pg/tuple_spec.rb +55 -2
  52. data/spec/pg/type_map_by_column_spec.rb +5 -1
  53. data/spec/pg/type_spec.rb +180 -6
  54. metadata +17 -15
  55. metadata.gz.sig +0 -0
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_type_map.c,v 2af122820861 2017/01/14 19:56:36 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_all_strings.c - PG::TypeMapAllStrings class extension
3
- * $Id: pg_type_map_all_strings.c,v c53f993a4254 2014/12/12 21:57:29 lars $
3
+ * $Id$
4
4
  *
5
5
  * This is the default typemap.
6
6
  *
@@ -33,9 +33,9 @@ pg_tmas_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
33
33
  len = PQgetlength( p_result->pgresult, tuple, field );
34
34
 
35
35
  if ( 0 == PQfformat(p_result->pgresult, field) ) {
36
- ret = pg_text_dec_string(NULL, val, len, tuple, field, ENCODING_GET(result));
36
+ ret = pg_text_dec_string(NULL, val, len, tuple, field, p_result->enc_idx);
37
37
  } else {
38
- ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, ENCODING_GET(result));
38
+ ret = pg_bin_dec_bytea(NULL, val, len, tuple, field, p_result->enc_idx);
39
39
  }
40
40
 
41
41
  return ret;
@@ -99,7 +99,7 @@ init_pg_type_map_all_strings()
99
99
  * This type map casts all values received from the database server to Strings
100
100
  * and sends all values to the server after conversion to String by +#to_s+ .
101
101
  * That means, it is hard coded to PG::TextEncoder::String for value encoding
102
- * and to PG::TextDecoder::String for text format respectivly PG::BinaryDecoder::Bytea
102
+ * and to PG::TextDecoder::String for text format respectively PG::BinaryDecoder::Bytea
103
103
  * for binary format received from the server.
104
104
  *
105
105
  * It is suitable for type casting query bind parameters, result values and
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_class.c - PG::TypeMapByClass class extension
3
- * $Id: pg_type_map_by_class.c,v eeb8a82c5328 2014/11/10 19:34:02 lars $
3
+ * $Id$
4
4
  *
5
5
  * This type map can be used to select value encoders based on the class
6
6
  * of the given value to be send.
@@ -28,7 +28,7 @@ typedef struct {
28
28
  * We use 8 Bits of the klass object id as index to a 256 entry cache.
29
29
  * This avoids full lookups in most cases.
30
30
  */
31
- #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(klass >> 8) & 0xff] )
31
+ #define CACHE_LOOKUP(this, klass) ( &this->cache_row[(((unsigned long)klass) >> 8) & 0xff] )
32
32
 
33
33
 
34
34
  static t_pg_coder *
@@ -66,7 +66,7 @@ pg_tmbk_lookup_klass(t_tmbk *this, VALUE klass, VALUE param_value)
66
66
  Data_Get_Struct(obj, t_pg_coder, p_coder);
67
67
  }else{
68
68
  if( RB_TYPE_P(obj, T_SYMBOL) ){
69
- /* A Proc object (or something that responds to #call). */
69
+ /* A Symbol: Call the method with this name. */
70
70
  obj = rb_funcall(this->self, SYM2ID(obj), 1, param_value);
71
71
  }else{
72
72
  /* A Proc object (or something that responds to #call). */
@@ -235,5 +235,6 @@ init_pg_type_map_by_class()
235
235
  rb_define_method( rb_cTypeMapByClass, "[]=", pg_tmbk_aset, 2 );
236
236
  rb_define_method( rb_cTypeMapByClass, "[]", pg_tmbk_aref, 1 );
237
237
  rb_define_method( rb_cTypeMapByClass, "coders", pg_tmbk_coders, 0 );
238
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
238
239
  rb_include_module( rb_cTypeMapByClass, rb_mDefaultTypeMappable );
239
240
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_column_map.c - PG::ColumnMap class extension
3
- * $Id: pg_type_map_by_column.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -99,11 +99,11 @@ pg_tmbc_result_value( t_typemap *p_typemap, VALUE result, int tuple, int field )
99
99
  int len = PQgetlength( p_result->pgresult, tuple, field );
100
100
 
101
101
  if( p_coder->dec_func ){
102
- return p_coder->dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result));
102
+ return p_coder->dec_func(p_coder, val, len, tuple, field, p_result->enc_idx);
103
103
  } else {
104
104
  t_pg_coder_dec_func dec_func;
105
105
  dec_func = pg_coder_dec_func( p_coder, PQfformat(p_result->pgresult, field) );
106
- return dec_func(p_coder, val, len, tuple, field, ENCODING_GET(result));
106
+ return dec_func(p_coder, val, len, tuple, field, p_result->enc_idx);
107
107
  }
108
108
  }
109
109
 
@@ -292,13 +292,13 @@ init_pg_type_map_by_column()
292
292
  *
293
293
  * This type map casts values by a coder assigned per field/column.
294
294
  *
295
- * Each PG:TypeMapByColumn has a fixed list of either encoders or decoders,
296
- * that is defined at #new . A type map with encoders is usable for type casting
295
+ * Each PG::TypeMapByColumn has a fixed list of either encoders or decoders,
296
+ * that is defined at TypeMapByColumn.new . A type map with encoders is usable for type casting
297
297
  * query bind parameters and COPY data for PG::Connection#put_copy_data .
298
298
  * A type map with decoders is usable for type casting of result values and
299
299
  * COPY data from PG::Connection#get_copy_data .
300
300
  *
301
- * PG::TypeMapByColumns are in particular useful in conjunction with prepared statements,
301
+ * PG::TypeMapByColumn objects are in particular useful in conjunction with prepared statements,
302
302
  * since they can be cached alongside with the statement handle.
303
303
  *
304
304
  * This type map strategy is also used internally by PG::TypeMapByOid, when the
@@ -308,5 +308,6 @@ init_pg_type_map_by_column()
308
308
  rb_define_alloc_func( rb_cTypeMapByColumn, pg_tmbc_s_allocate );
309
309
  rb_define_method( rb_cTypeMapByColumn, "initialize", pg_tmbc_init, 1 );
310
310
  rb_define_method( rb_cTypeMapByColumn, "coders", pg_tmbc_coders, 0 );
311
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
311
312
  rb_include_module( rb_cTypeMapByColumn, rb_mDefaultTypeMappable );
312
313
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_mri_type.c - PG::TypeMapByMriType class extension
3
- * $Id: pg_type_map_by_mri_type.c,v 1269b8ad77b8 2015/02/06 16:38:23 lars $
3
+ * $Id$
4
4
  *
5
5
  * This type map can be used to select value encoders based on the MRI-internal
6
6
  * value type code.
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_by_oid.c - PG::TypeMapByOid class extension
3
- * $Id: pg_type_map_by_oid.c,v c99d26015e3c 2014/12/12 20:58:25 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -110,7 +110,7 @@ pg_tmbo_result_value(t_typemap *p_typemap, VALUE result, int tuple, int field)
110
110
  char * val = PQgetvalue( p_result->pgresult, tuple, field );
111
111
  int len = PQgetlength( p_result->pgresult, tuple, field );
112
112
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, format );
113
- return dec_func( p_coder, val, len, tuple, field, ENCODING_GET(result) );
113
+ return dec_func( p_coder, val, len, tuple, field, p_result->enc_idx );
114
114
  }
115
115
 
116
116
  default_tm = DATA_PTR( this->typemap.default_typemap );
@@ -351,5 +351,6 @@ init_pg_type_map_by_oid()
351
351
  rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup=", pg_tmbo_max_rows_for_online_lookup_set, 1 );
352
352
  rb_define_method( rb_cTypeMapByOid, "max_rows_for_online_lookup", pg_tmbo_max_rows_for_online_lookup_get, 0 );
353
353
  rb_define_method( rb_cTypeMapByOid, "build_column_map", pg_tmbo_build_column_map, 1 );
354
+ /* rb_mDefaultTypeMappable = rb_define_module_under( rb_cTypeMap, "DefaultTypeMappable"); */
354
355
  rb_include_module( rb_cTypeMapByOid, rb_mDefaultTypeMappable );
355
356
  }
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_type_map_in_ruby.c - PG::TypeMapInRuby class extension
3
- * $Id: pg_type_map_in_ruby.c,v 3d89d3aae4fd 2015/01/05 16:19:41 kanis $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -1,11 +1,11 @@
1
1
  /*
2
- * util.c - Utils for ruby-pg
3
- * $Id: util.c,v fc1c4deb1398 2018/06/25 12:02:09 kanis $
2
+ * pg_util.c - Utils for ruby-pg
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
7
7
  #include "pg.h"
8
- #include "util.h"
8
+ #include "pg_util.h"
9
9
 
10
10
  static const char base64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
11
11
 
@@ -22,12 +22,12 @@ base64_encode( char *out, const char *in, int len)
22
22
  int part_len = len % 3;
23
23
 
24
24
  if( part_len > 0 ){
25
- long byte2 = part_len > 2 ? *--in_ptr : 0;
25
+ long byte2 = 0;
26
26
  long byte1 = part_len > 1 ? *--in_ptr : 0;
27
27
  long byte0 = *--in_ptr;
28
28
  long triple = (byte0 << 16) + (byte1 << 8) + byte2;
29
29
 
30
- *--out_ptr = part_len > 2 ? base64_encode_table[(triple >> 0 * 6) & 0x3F] : '=';
30
+ *--out_ptr = '=';
31
31
  *--out_ptr = part_len > 1 ? base64_encode_table[(triple >> 1 * 6) & 0x3F] : '=';
32
32
  *--out_ptr = base64_encode_table[(triple >> 2 * 6) & 0x3F];
33
33
  *--out_ptr = base64_encode_table[(triple >> 3 * 6) & 0x3F];
File without changes
data/lib/pg.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- ruby -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  begin
4
5
  require 'pg_ext'
@@ -35,7 +36,7 @@ end
35
36
  module PG
36
37
 
37
38
  # Library version
38
- VERSION = '1.1.4'
39
+ VERSION = '1.2.0'
39
40
 
40
41
  # VCS revision
41
42
  REVISION = %q$Revision: 6f611e78845a $
@@ -70,5 +71,3 @@ module PG
70
71
  require 'pg/tuple'
71
72
 
72
73
  end # module PG
73
-
74
-
@@ -1,4 +1,5 @@
1
1
  # -*- ruby -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pg' unless defined?( PG )
4
5
 
@@ -154,14 +155,26 @@ module PG::BasicTypeRegistry
154
155
  # objects as values.
155
156
  CODERS_BY_NAME = []
156
157
 
157
- # Register an OID type named +name+ with a typecasting encoder and decoder object in
158
- # +type+. +name+ should correspond to the `typname` column in
159
- # the `pg_type` table.
158
+ public
159
+
160
+ # Register an encoder or decoder instance for casting a PostgreSQL type.
161
+ #
162
+ # Coder#name must correspond to the +typname+ column in the +pg_type+ table.
163
+ # Coder#format can be 0 for text format and 1 for binary.
164
+ def self.register_coder(coder)
165
+ h = CODERS_BY_NAME[coder.format] ||= { encoder: {}, decoder: {} }
166
+ name = coder.name || raise(ArgumentError, "name of #{coder.inspect} must be defined")
167
+ h[:encoder][name] = coder if coder.respond_to?(:encode)
168
+ h[:decoder][name] = coder if coder.respond_to?(:decode)
169
+ end
170
+
171
+ # Register the given +encoder_class+ and/or +decoder_class+ for casting a PostgreSQL type.
172
+ #
173
+ # +name+ must correspond to the +typname+ column in the +pg_type+ table.
160
174
  # +format+ can be 0 for text format and 1 for binary.
161
175
  def self.register_type(format, name, encoder_class, decoder_class)
162
- CODERS_BY_NAME[format] ||= { encoder: {}, decoder: {} }
163
- CODERS_BY_NAME[format][:encoder][name] = encoder_class.new(name: name, format: format) if encoder_class
164
- CODERS_BY_NAME[format][:decoder][name] = decoder_class.new(name: name, format: format) if decoder_class
176
+ register_coder(encoder_class.new(name: name, format: format)) if encoder_class
177
+ register_coder(decoder_class.new(name: name, format: format)) if decoder_class
165
178
  end
166
179
 
167
180
  # Alias the +old+ type to the +new+ type.
@@ -247,7 +260,7 @@ end
247
260
  # Simple set of rules for type casting common PostgreSQL types to Ruby.
248
261
  #
249
262
  # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
250
- # PostgreSQL's pg_type table in PG::BasicTypeMapForResults.new .
263
+ # PostgreSQL's +pg_type+ table in PG::BasicTypeMapForResults.new .
251
264
  #
252
265
  # Result values are type casted based on the type OID of the given result column.
253
266
  #
@@ -264,7 +277,7 @@ end
264
277
  # # is done by PG::TextDecoder::Integer internally for all value retrieval methods.
265
278
  # res.values # => [[5]]
266
279
  #
267
- # PG::TypeMapByOid#fit_to_result(result, false) can be used to generate
280
+ # PG::TypeMapByOid#build_column_map(result) can be used to generate
268
281
  # a result independent PG::TypeMapByColumn type map, which can subsequently be used
269
282
  # to cast #get_copy_data fields:
270
283
  #
@@ -301,7 +314,7 @@ class PG::BasicTypeMapForResults < PG::TypeMapByOid
301
314
  format = result.fformat(field)
302
315
  oid = result.ftype(field)
303
316
  unless @already_warned[format][oid]
304
- STDERR.puts "Warning: no type cast defined for type #{@typenames_by_oid[format][oid].inspect} with oid #{oid}. Please cast this type explicitly to TEXT to be safe for future changes."
317
+ $stderr.puts "Warning: no type cast defined for type #{@typenames_by_oid[format][oid].inspect} with oid #{oid}. Please cast this type explicitly to TEXT to be safe for future changes."
305
318
  @already_warned[format][oid] = true
306
319
  end
307
320
  super
@@ -325,7 +338,7 @@ end
325
338
  # to PostgreSQL.
326
339
  #
327
340
  # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
328
- # PostgreSQL's pg_type table in PG::BasicTypeMapBasedOnResult.new .
341
+ # PostgreSQL's +pg_type+ table in PG::BasicTypeMapBasedOnResult.new .
329
342
  #
330
343
  # This class works equal to PG::BasicTypeMapForResults, but does not define decoders for
331
344
  # the given result OIDs, but encoders. So it can be used to type cast field values based on
@@ -380,21 +393,54 @@ end
380
393
  # # Assign a default ruleset for type casts of input and output values.
381
394
  # conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
382
395
  # # Execute a query. The Integer param value is typecasted internally by PG::BinaryEncoder::Int8.
383
- # # The format of the parameter is set to 1 (binary) and the OID of this parameter is set to 20 (int8).
396
+ # # The format of the parameter is set to 0 (text) and the OID of this parameter is set to 20 (int8).
384
397
  # res = conn.exec_params( "SELECT $1", [5] )
385
398
  class PG::BasicTypeMapForQueries < PG::TypeMapByClass
386
399
  include PG::BasicTypeRegistry
387
400
 
388
401
  def initialize(connection)
389
402
  @coder_maps = build_coder_maps(connection)
390
-
391
- populate_encoder_list
392
403
  @array_encoders_by_klass = array_encoders_by_klass
393
- @anyarray_encoder = coder_by_name(0, :encoder, '_any')
404
+ @encode_array_as = :array
405
+ init_encoders
406
+ end
407
+
408
+ # Change the mechanism that is used to encode ruby array values
409
+ #
410
+ # Possible values:
411
+ # * +:array+ : Encode the ruby array as a PostgreSQL array.
412
+ # The array element type is inferred from the class of the first array element. This is the default.
413
+ # * +:json+ : Encode the ruby array as a JSON document.
414
+ # * +:record+ : Encode the ruby array as a composite type row.
415
+ # * <code>"_type"</code> : Encode the ruby array as a particular PostgreSQL type.
416
+ # All PostgreSQL array types are supported.
417
+ # If there's an encoder registered for the elements +type+, it will be used.
418
+ # Otherwise a string conversion (by +value.to_s+) is done.
419
+ def encode_array_as=(pg_type)
420
+ case pg_type
421
+ when :array
422
+ when :json
423
+ when :record
424
+ when /\A_/
425
+ else
426
+ raise ArgumentError, "invalid pg_type #{pg_type.inspect}"
427
+ end
428
+
429
+ @encode_array_as = pg_type
430
+
431
+ init_encoders
394
432
  end
395
433
 
434
+ attr_reader :encode_array_as
435
+
396
436
  private
397
437
 
438
+ def init_encoders
439
+ coders.each { |kl, c| self[kl] = nil } # Clear type map
440
+ populate_encoder_list
441
+ @textarray_encoder = coder_by_name(0, :encoder, '_text')
442
+ end
443
+
398
444
  def coder_by_name(format, direction, name)
399
445
  check_format_and_direction(format, direction)
400
446
  @coder_maps[format][direction].coder_by_name(name)
@@ -412,7 +458,19 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
412
458
  end
413
459
  self[klass] = coder
414
460
  else
415
- self[klass] = selector
461
+
462
+ case @encode_array_as
463
+ when :array
464
+ self[klass] = selector
465
+ when :json
466
+ self[klass] = PG::TextEncoder::JSON.new
467
+ when :record
468
+ self[klass] = PG::TextEncoder::Record.new type_map: self
469
+ when /\A_/
470
+ self[klass] = coder_by_name(0, :encoder, @encode_array_as) || raise(ArgumentError, "unknown array type #{@encode_array_as.inspect}")
471
+ else
472
+ raise ArgumentError, "invalid pg_type #{@encode_array_as.inspect}"
473
+ end
416
474
  end
417
475
  end
418
476
  end
@@ -431,7 +489,7 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
431
489
  end
432
490
  @array_encoders_by_klass[elem.class] ||
433
491
  elem.class.ancestors.lazy.map{|ancestor| @array_encoders_by_klass[ancestor] }.find{|a| a } ||
434
- @anyarray_encoder
492
+ @textarray_encoder
435
493
  end
436
494
 
437
495
  DEFAULT_TYPE_MAP = {
@@ -442,9 +500,11 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
442
500
  Integer => [0, 'int8'],
443
501
  Float => [0, 'float8'],
444
502
  BigDecimal => [0, 'numeric'],
503
+ Time => [0, 'timestamptz'],
445
504
  # We use text format and no type OID for IPAddr, because setting the OID can lead
446
505
  # to unnecessary inet/cidr conversions on the server side.
447
506
  IPAddr => [0, 'inet'],
507
+ Hash => [0, 'json'],
448
508
  Array => :get_array_type,
449
509
  }
450
510
 
@@ -454,6 +514,9 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
454
514
  Integer => [0, '_int8'],
455
515
  String => [0, '_text'],
456
516
  Float => [0, '_float8'],
517
+ BigDecimal => [0, '_numeric'],
518
+ Time => [0, '_timestamptz'],
519
+ IPAddr => [0, '_inet'],
457
520
  }
458
521
 
459
522
  end
@@ -1,4 +1,5 @@
1
1
  # -*- ruby -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  module PG
4
5
  module BinaryDecoder
@@ -1,4 +1,5 @@
1
1
  # -*- ruby -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  module PG
4
5
 
@@ -28,6 +29,7 @@ module PG
28
29
  {
29
30
  oid: oid,
30
31
  format: format,
32
+ flags: flags,
31
33
  name: name,
32
34
  }
33
35
  end
@@ -52,6 +54,18 @@ module PG
52
54
  str[-1,0] = "#{name_str} #{oid_str}#{format_str}"
53
55
  str
54
56
  end
57
+
58
+ def inspect_short
59
+ str = case format
60
+ when 0 then "T"
61
+ when 1 then "B"
62
+ else format.to_s
63
+ end
64
+ str += "E" if respond_to?(:encode)
65
+ str += "D" if respond_to?(:decode)
66
+
67
+ "#{name || self.class.name}:#{str}"
68
+ end
55
69
  end
56
70
 
57
71
  class CompositeCoder < Coder
@@ -79,5 +93,12 @@ module PG
79
93
  })
80
94
  end
81
95
  end
82
- end # module PG
83
96
 
97
+ class RecordCoder < Coder
98
+ def to_h
99
+ super.merge!({
100
+ type_map: type_map,
101
+ })
102
+ end
103
+ end
104
+ end # module PG
@@ -1,4 +1,5 @@
1
1
  # -*- ruby -*-
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'pg' unless defined?( PG )
4
5
  require 'uri'
@@ -47,7 +48,7 @@ class PG::Connection
47
48
 
48
49
  if args.length == 1
49
50
  case args.first
50
- when URI, /\A#{URI.regexp}\z/
51
+ when URI, /\A#{URI::ABS_URI_REF}\z/
51
52
  uri = URI(args.first)
52
53
  options.merge!( Hash[URI.decode_www_form( uri.query )] ) if uri.query
53
54
  when /=/
@@ -288,4 +289,3 @@ class PG::Connection
288
289
  # pg-1.1.0+ defaults to libpq's async API for query related blocking methods
289
290
  self.async_api = true
290
291
  end # class PG::Connection
291
-