pg 0.18.0.pre20141017155815 → 0.18.0.pre20141017160319

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 95311a9d99ccb8ee189f70f82db3c3246482cf5f
4
- data.tar.gz: 72e13155d8032762a39b0628b882acb55325f8a2
3
+ metadata.gz: db79067db275bd6f5d8fb5194610716de4eba838
4
+ data.tar.gz: 30aa3c6d3ea706306adc3059b16349429f2c15c6
5
5
  SHA512:
6
- metadata.gz: 2497dbc6ea9a9ea96fc6731b548b7d0c49c38be819b5b4eb927f432483e7df35603bf4247a14936cb566702ff6c90361e4e9cd815c97d75ca88b367ac8fdc184
7
- data.tar.gz: d8475aef22cda0e31655b5edb58838b83c6dafe2e2fd5f10a051901af817c80f2d569a97d096bbdbbf1ef6f67017666661acedef70364010bacdddc5bce5f640
6
+ metadata.gz: 76c17fe2bbbdcf10ffe5e6ba71fde8babc6723ff8a3673455fc647a77f8f718caecf77cab6e255a45c46db01cfaa1fde83db75a26cb39712e10e462f143629ed
7
+ data.tar.gz: 77b0e5b2993e2c1a2c5a31a7ad2ffd3bd2ed292111e07bf6fc96f85074001d9434f2a9e6614aefb5f931c0534b4ba1611de54e9f0000e558790606f88aeab5ac
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,10 +1,28 @@
1
+ 2014-10-15 Lars Kanis <lars@greiz-reinsdorf.de>
2
+
3
+ * ext/pg_text_encoder.c, spec/pg/type_spec.rb:
4
+ Allow non Array values as input for TextEncoder::Array.
5
+ [a4725dfca9e4] [tip]
6
+
7
+ * ext/pg_coder.c, spec/pg/type_spec.rb:
8
+ Clarify handling of nil/NULL values by PG::Coders.
9
+ [99d6acb8b66d]
10
+
11
+ * ext/pg_text_encoder.c, ext/util.c, ext/util.h:
12
+ Move pg_strncasecmp() to util.c - it better fits there.
13
+ [117fb5c5eed7]
14
+
1
15
  2014-10-14 Lars Kanis <lars@greiz-reinsdorf.de>
2
16
 
17
+ * ext/pg_text_encoder.c, spec/pg/type_spec.rb:
18
+ Implement a more serious TestEncoder::Boolean.
19
+ [9063a84a2ff9]
20
+
3
21
  * ext/pg.h, ext/pg_binary_encoder.c, ext/pg_coder.c,
4
22
  ext/pg_text_encoder.c:
5
23
  Fix naming and description of pg_coder_enc_to_s(). It actually uses
6
24
  #to_s not #to_str.
7
- [ac23631c96d9] [github/master, tip]
25
+ [ac23631c96d9] [github/master]
8
26
 
9
27
  * ext/pg_text_encoder.c, spec/pg/type_spec.rb:
10
28
  Use same rules for array quoting in text encoder as PostgreSQL.
@@ -109,6 +109,8 @@ pg_composite_decoder_allocate( VALUE klass )
109
109
  * Encodes the given Ruby object into string representation, without
110
110
  * sending data to/from the database server.
111
111
  *
112
+ * A nil value is passed through.
113
+ *
112
114
  */
113
115
  static VALUE
114
116
  pg_coder_encode(VALUE self, VALUE value)
@@ -118,6 +120,9 @@ pg_coder_encode(VALUE self, VALUE value)
118
120
  int len, len2;
119
121
  t_pg_coder *this = DATA_PTR(self);
120
122
 
123
+ if( NIL_P(value) )
124
+ return Qnil;
125
+
121
126
  if( !this->enc_func ){
122
127
  rb_raise(rb_eRuntimeError, "no encoder function defined");
123
128
  }
@@ -151,6 +156,9 @@ pg_coder_encode(VALUE self, VALUE value)
151
156
  * Decodes the given string representation into a Ruby object, without
152
157
  * sending data to/from the database server.
153
158
  *
159
+ * A nil value is passed through and non String values are expected to have
160
+ * #to_str defined.
161
+ *
154
162
  */
155
163
  static VALUE
156
164
  pg_coder_decode(int argc, VALUE *argv, VALUE self)
@@ -168,6 +176,9 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
168
176
  field = NUM2INT(argv[2]);
169
177
  }
170
178
 
179
+ if( NIL_P(argv[0]) )
180
+ return Qnil;
181
+
171
182
  val = StringValuePtr(argv[0]);
172
183
  if( !this->dec_func ){
173
184
  rb_raise(rb_eRuntimeError, "no decoder function defined");
@@ -406,6 +417,14 @@ init_pg_coder()
406
417
  /* Document-class: PG::Coder < Object
407
418
  *
408
419
  * This is the base class for all type cast encoder and decoder classes.
420
+ *
421
+ * It can be used for implicit type casts by a PG::TypeMap or to
422
+ * convert single values to/from their string representation by #encode
423
+ * and #decode.
424
+ *
425
+ * Ruby +nil+ values are not handled by encoders, but are always transmitted
426
+ * as SQL +NULL+ value. Vice versa SQL +NULL+ values are not handled by decoders,
427
+ * but are always returned as a +nil+ value.
409
428
  */
410
429
  rb_cPG_Coder = rb_define_class_under( rb_mPG, "Coder", rb_cObject );
411
430
  rb_define_alloc_func( rb_cPG_Coder, pg_coder_allocate );
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_text_encoder.c - PG::TextEncoder module
3
- * $Id: pg_text_encoder.c,v ac23631c96d9 2014/10/14 11:50:21 lars $
3
+ * $Id: pg_text_encoder.c,v a4725dfca9e4 2014/10/15 19:50:56 lars $
4
4
  *
5
5
  */
6
6
 
@@ -46,6 +46,7 @@
46
46
  VALUE rb_mPG_TextEncoder;
47
47
  static ID s_id_encode;
48
48
  static ID s_id_to_i;
49
+ static VALUE hash_false_values;
49
50
 
50
51
 
51
52
  VALUE
@@ -66,7 +67,39 @@ pg_obj_to_i( VALUE value )
66
67
  *
67
68
  * This is the encoder class for the PostgreSQL bool type.
68
69
  *
70
+ * Ruby values false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off' and 'OFF'
71
+ * are encoded as SQL +FALSE+ value. nil is sent as SQL +NULL+.
72
+ * Any other values are encoded as SQL +TRUE+ .
73
+ *
69
74
  */
75
+ static int
76
+ pg_text_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
77
+ {
78
+ if(out){
79
+ switch( TYPE(value) ){
80
+ case T_FALSE:
81
+ *out = 'f';
82
+ break;
83
+ case T_FIXNUM:
84
+ case T_BIGNUM:
85
+ if( NUM2LONG(value) == 0 ){
86
+ *out = 'f';
87
+ } else {
88
+ *out = 't';
89
+ }
90
+ break;
91
+ case T_STRING:
92
+ if( rb_hash_lookup(hash_false_values, value) == Qtrue ){
93
+ *out = 'f';
94
+ break;
95
+ }
96
+ /* fall through */
97
+ default:
98
+ *out = 't';
99
+ }
100
+ }
101
+ return 1;
102
+ }
70
103
 
71
104
 
72
105
  /*
@@ -213,34 +246,6 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
213
246
  }
214
247
  }
215
248
 
216
- /*
217
- * Case-independent comparison of two not-necessarily-null-terminated strings.
218
- * At most n bytes will be examined from each string.
219
- */
220
- static int
221
- pg_strncasecmp(const char *s1, const char *s2, size_t n)
222
- {
223
- while (n-- > 0)
224
- {
225
- unsigned char ch1 = (unsigned char) *s1++;
226
- unsigned char ch2 = (unsigned char) *s2++;
227
-
228
- if (ch1 != ch2){
229
- if (ch1 >= 'A' && ch1 <= 'Z')
230
- ch1 += 'a' - 'A';
231
-
232
- if (ch2 >= 'A' && ch2 <= 'Z')
233
- ch2 += 'a' - 'A';
234
-
235
- if (ch1 != ch2)
236
- return (int) ch1 - (int) ch2;
237
- }
238
- if (ch1 == 0)
239
- break;
240
- }
241
- return 0;
242
- }
243
-
244
249
  typedef int (*t_quote_func)( void *_this, char *p_in, int strlen, char *p_out );
245
250
 
246
251
  static int
@@ -387,19 +392,27 @@ write_array(t_pg_composite_coder *this, VALUE value, char *current_out, VALUE st
387
392
  * All values are encoded according to the #elements_type
388
393
  * accessor. Sub-arrays are encoded recursively.
389
394
  *
395
+ * This encoder expects an Array of values or sub-arrays as input.
396
+ * Other values are passed through as text without interpretation.
397
+ *
390
398
  */
391
399
  static int
392
400
  pg_text_enc_array(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
393
401
  {
394
402
  char *end_ptr;
395
403
  t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
396
- *intermediate = rb_str_new(NULL, 0);
397
404
 
398
- end_ptr = write_array(this, value, RSTRING_PTR(*intermediate), *intermediate, this->needs_quotation);
405
+ if( TYPE(value) == T_ARRAY){
406
+ *intermediate = rb_str_new(NULL, 0);
399
407
 
400
- rb_str_set_len( *intermediate, end_ptr - RSTRING_PTR(*intermediate) );
408
+ end_ptr = write_array(this, value, RSTRING_PTR(*intermediate), *intermediate, this->needs_quotation);
401
409
 
402
- return -1;
410
+ rb_str_set_len( *intermediate, end_ptr - RSTRING_PTR(*intermediate) );
411
+
412
+ return -1;
413
+ } else {
414
+ return pg_coder_enc_to_s( conv, value, out, intermediate );
415
+ }
403
416
  }
404
417
 
405
418
  static int
@@ -584,12 +597,22 @@ init_pg_text_encoder()
584
597
  s_id_encode = rb_intern("encode");
585
598
  s_id_to_i = rb_intern("to_i");
586
599
 
600
+ hash_false_values = rb_hash_new();
601
+ rb_gc_register_address( &hash_false_values );
602
+ rb_hash_aset( hash_false_values, rb_str_new2( "0" ), Qtrue );
603
+ rb_hash_aset( hash_false_values, rb_str_new2( "f" ), Qtrue );
604
+ rb_hash_aset( hash_false_values, rb_str_new2( "F" ), Qtrue );
605
+ rb_hash_aset( hash_false_values, rb_str_new2( "false" ), Qtrue );
606
+ rb_hash_aset( hash_false_values, rb_str_new2( "FALSE" ), Qtrue );
607
+ rb_hash_aset( hash_false_values, rb_str_new2( "off" ), Qtrue );
608
+ rb_hash_aset( hash_false_values, rb_str_new2( "OFF" ), Qtrue );
609
+
587
610
  /* This module encapsulates all encoder classes with text output format */
588
611
  rb_mPG_TextEncoder = rb_define_module_under( rb_mPG, "TextEncoder" );
589
612
 
590
613
  /* Make RDoc aware of the encoder classes... */
591
614
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Boolean", rb_cPG_SimpleEncoder ); */
592
- pg_define_coder( "Boolean", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
615
+ pg_define_coder( "Boolean", pg_text_enc_boolean, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
593
616
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Integer", rb_cPG_SimpleEncoder ); */
594
617
  pg_define_coder( "Integer", pg_text_enc_integer, rb_cPG_SimpleEncoder, rb_mPG_TextEncoder );
595
618
  /* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Float", rb_cPG_SimpleEncoder ); */
data/ext/util.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * util.c - Utils for ruby-pg
3
- * $Id: util.c,v c8d7c26dd595 2014/10/12 17:08:46 lars $
3
+ * $Id: util.c,v 117fb5c5eed7 2014/10/15 18:36:39 lars $
4
4
  *
5
5
  */
6
6
 
@@ -119,3 +119,31 @@ base64_decode( char *out, char *in, unsigned int len)
119
119
  return (char*)out_ptr - out;
120
120
  }
121
121
 
122
+ /*
123
+ * Case-independent comparison of two not-necessarily-null-terminated strings.
124
+ * At most n bytes will be examined from each string.
125
+ */
126
+ int
127
+ pg_strncasecmp(const char *s1, const char *s2, size_t n)
128
+ {
129
+ while (n-- > 0)
130
+ {
131
+ unsigned char ch1 = (unsigned char) *s1++;
132
+ unsigned char ch2 = (unsigned char) *s2++;
133
+
134
+ if (ch1 != ch2){
135
+ if (ch1 >= 'A' && ch1 <= 'Z')
136
+ ch1 += 'a' - 'A';
137
+
138
+ if (ch2 >= 'A' && ch2 <= 'Z')
139
+ ch2 += 'a' - 'A';
140
+
141
+ if (ch1 != ch2)
142
+ return (int) ch1 - (int) ch2;
143
+ }
144
+ if (ch1 == 0)
145
+ break;
146
+ }
147
+ return 0;
148
+ }
149
+
data/ext/util.h CHANGED
@@ -60,4 +60,6 @@
60
60
  void base64_encode( char *out, char *in, int len);
61
61
  int base64_decode( char *out, char *in, unsigned int len);
62
62
 
63
+ int pg_strncasecmp(const char *s1, const char *s2, size_t n);
64
+
63
65
  #endif /* end __utils_h */
@@ -7,6 +7,8 @@ require 'pg'
7
7
  describe "PG::Type derivations" do
8
8
  let!(:textenc_int) { PG::TextEncoder::Integer.new name: 'Integer', oid: 23 }
9
9
  let!(:textdec_int) { PG::TextDecoder::Integer.new name: 'Integer', oid: 23 }
10
+ let!(:textenc_boolean) { PG::TextEncoder::Boolean.new }
11
+ let!(:textdec_boolean) { PG::TextDecoder::Boolean.new }
10
12
  let!(:textenc_float) { PG::TextEncoder::Float.new }
11
13
  let!(:textdec_float) { PG::TextDecoder::Float.new }
12
14
  let!(:textenc_string) { PG::TextEncoder::String.new }
@@ -88,6 +90,11 @@ describe "PG::Type derivations" do
88
90
  expect{ textdec_int.decode(2, 3, 4) }.to raise_error(TypeError)
89
91
  expect( intdec_incrementer.decode(2, 3, 4) ).to eq( 3 )
90
92
  end
93
+
94
+ it "should pass through nil values" do
95
+ expect( textdec_string.encode( nil )).to be_nil
96
+ expect( textdec_int.encode( nil )).to be_nil
97
+ end
91
98
  end
92
99
 
93
100
  describe '#encode' do
@@ -130,6 +137,18 @@ describe "PG::Type derivations" do
130
137
  expect( textenc_int.encode(" 123-xyz ") ).to eq( "123" )
131
138
  end
132
139
 
140
+ it "should encode false and 0 to SQL FALSE value" do
141
+ [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].each do |value|
142
+ expect( textenc_boolean.encode(value) ).to eq( "f" )
143
+ end
144
+ end
145
+
146
+ it "should encode true, 1 to SQL TRUE value" do
147
+ [true, 1, '1', 't', 'T', 'true', 'TRUE', 'on', 'ON'].each do |value|
148
+ expect( textenc_boolean.encode(value) ).to eq( "t" )
149
+ end
150
+ end
151
+
133
152
  it "should encode special floats equally to Float#to_s" do
134
153
  expect( textenc_float.encode(Float::INFINITY) ).to eq( Float::INFINITY.to_s )
135
154
  expect( textenc_float.encode(-Float::INFINITY) ).to eq( (-Float::INFINITY).to_s )
@@ -143,6 +162,11 @@ describe "PG::Type derivations" do
143
162
  it "should return when ruby encoder returns non string values" do
144
163
  expect( intenc_incrementer_with_int_result.encode(3) ).to eq( 4 )
145
164
  end
165
+
166
+ it "should pass through nil values" do
167
+ expect( textenc_string.encode( nil )).to be_nil
168
+ expect( textenc_int.encode( nil )).to be_nil
169
+ end
146
170
  end
147
171
 
148
172
  it "should be possible to marshal encoders" do
@@ -377,6 +401,11 @@ describe "PG::Type derivations" do
377
401
  end
378
402
  end
379
403
 
404
+ it "should pass through non Array inputs" do
405
+ expect( textenc_float_array.encode("text") ).to eq( "text" )
406
+ expect( textenc_float_array.encode(1234) ).to eq( "1234" )
407
+ end
408
+
380
409
  context 'identifier quotation' do
381
410
  it 'should quote and escape identifier' do
382
411
  quoted_type = PG::TextEncoder::Identifier.new elements_type: textenc_string
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0.pre20141017155815
4
+ version: 0.18.0.pre20141017160319
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
metadata.gz.sig CHANGED
Binary file