pg 0.17.1 → 0.18.4

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 (53) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/ChangeLog +2407 -2
  4. data/History.rdoc +68 -0
  5. data/Manifest.txt +29 -1
  6. data/README-Windows.rdoc +15 -26
  7. data/README.rdoc +52 -2
  8. data/Rakefile +56 -18
  9. data/Rakefile.cross +77 -49
  10. data/ext/extconf.rb +33 -26
  11. data/ext/pg.c +142 -21
  12. data/ext/pg.h +242 -6
  13. data/ext/pg_binary_decoder.c +162 -0
  14. data/ext/pg_binary_encoder.c +162 -0
  15. data/ext/pg_coder.c +479 -0
  16. data/ext/pg_connection.c +858 -553
  17. data/ext/pg_copy_coder.c +561 -0
  18. data/ext/pg_errors.c +6 -0
  19. data/ext/pg_result.c +479 -128
  20. data/ext/pg_text_decoder.c +421 -0
  21. data/ext/pg_text_encoder.c +663 -0
  22. data/ext/pg_type_map.c +159 -0
  23. data/ext/pg_type_map_all_strings.c +116 -0
  24. data/ext/pg_type_map_by_class.c +239 -0
  25. data/ext/pg_type_map_by_column.c +312 -0
  26. data/ext/pg_type_map_by_mri_type.c +284 -0
  27. data/ext/pg_type_map_by_oid.c +355 -0
  28. data/ext/pg_type_map_in_ruby.c +299 -0
  29. data/ext/util.c +149 -0
  30. data/ext/util.h +65 -0
  31. data/lib/pg/basic_type_mapping.rb +399 -0
  32. data/lib/pg/coder.rb +83 -0
  33. data/lib/pg/connection.rb +81 -29
  34. data/lib/pg/result.rb +13 -3
  35. data/lib/pg/text_decoder.rb +44 -0
  36. data/lib/pg/text_encoder.rb +27 -0
  37. data/lib/pg/type_map_by_column.rb +15 -0
  38. data/lib/pg.rb +12 -2
  39. data/spec/{lib/helpers.rb → helpers.rb} +101 -39
  40. data/spec/pg/basic_type_mapping_spec.rb +251 -0
  41. data/spec/pg/connection_spec.rb +516 -218
  42. data/spec/pg/result_spec.rb +216 -112
  43. data/spec/pg/type_map_by_class_spec.rb +138 -0
  44. data/spec/pg/type_map_by_column_spec.rb +222 -0
  45. data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
  46. data/spec/pg/type_map_by_oid_spec.rb +149 -0
  47. data/spec/pg/type_map_in_ruby_spec.rb +164 -0
  48. data/spec/pg/type_map_spec.rb +22 -0
  49. data/spec/pg/type_spec.rb +697 -0
  50. data/spec/pg_spec.rb +24 -18
  51. data.tar.gz.sig +0 -0
  52. metadata +111 -45
  53. metadata.gz.sig +0 -0
@@ -0,0 +1,162 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id: pg_binary_decoder.c,v fcf731d3dff7 2015/09/08 12:25:06 jfali $
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+ #include "util.h"
9
+ #ifdef HAVE_INTTYPES_H
10
+ #include <inttypes.h>
11
+ #endif
12
+
13
+ VALUE rb_mPG_BinaryDecoder;
14
+
15
+
16
+ /*
17
+ * Document-class: PG::BinaryDecoder::Boolean < PG::SimpleDecoder
18
+ *
19
+ * This is a decoder class for conversion of PostgreSQL binary bool type
20
+ * to Ruby true or false objects.
21
+ *
22
+ */
23
+ static VALUE
24
+ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
25
+ {
26
+ if (len < 1) {
27
+ rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
28
+ }
29
+ return *val == 0 ? Qfalse : Qtrue;
30
+ }
31
+
32
+ /*
33
+ * Document-class: PG::BinaryDecoder::Integer < PG::SimpleDecoder
34
+ *
35
+ * This is a decoder class for conversion of PostgreSQL binary int2, int4 and int8 types
36
+ * to Ruby Integer objects.
37
+ *
38
+ */
39
+ static VALUE
40
+ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
41
+ {
42
+ switch( len ){
43
+ case 2:
44
+ return INT2NUM(read_nbo16(val));
45
+ case 4:
46
+ return LONG2NUM(read_nbo32(val));
47
+ case 8:
48
+ return LL2NUM(read_nbo64(val));
49
+ default:
50
+ rb_raise( rb_eTypeError, "wrong data for binary integer converter in tuple %d field %d length %d", tuple, field, len);
51
+ }
52
+ }
53
+
54
+ /*
55
+ * Document-class: PG::BinaryDecoder::Float < PG::SimpleDecoder
56
+ *
57
+ * This is a decoder class for conversion of PostgreSQL binary float4 and float8 types
58
+ * to Ruby Float objects.
59
+ *
60
+ */
61
+ static VALUE
62
+ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
63
+ {
64
+ union {
65
+ float f;
66
+ int32_t i;
67
+ } swap4;
68
+ union {
69
+ double f;
70
+ int64_t i;
71
+ } swap8;
72
+
73
+ switch( len ){
74
+ case 4:
75
+ swap4.i = read_nbo32(val);
76
+ return rb_float_new(swap4.f);
77
+ case 8:
78
+ swap8.i = read_nbo64(val);
79
+ return rb_float_new(swap8.f);
80
+ default:
81
+ rb_raise( rb_eTypeError, "wrong data for BinaryFloat converter in tuple %d field %d length %d", tuple, field, len);
82
+ }
83
+ }
84
+
85
+ /*
86
+ * Document-class: PG::BinaryDecoder::Bytea < PG::SimpleDecoder
87
+ *
88
+ * This decoder class delivers the data received from the server as binary String object.
89
+ * It is therefore suitable for conversion of PostgreSQL bytea data as well as any other
90
+ * data in binary format.
91
+ *
92
+ */
93
+ VALUE
94
+ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
95
+ {
96
+ VALUE ret;
97
+ ret = rb_tainted_str_new( val, len );
98
+ PG_ENCODING_SET_NOCHECK( ret, rb_ascii8bit_encindex() );
99
+ return ret;
100
+ }
101
+
102
+ /*
103
+ * Document-class: PG::BinaryDecoder::ToBase64 < PG::CompositeDecoder
104
+ *
105
+ * This is a decoder class for conversion of binary (bytea) to base64 data.
106
+ *
107
+ */
108
+ static VALUE
109
+ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
110
+ {
111
+ t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
112
+ t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
113
+ int encoded_len = BASE64_ENCODED_SIZE(len);
114
+ /* create a buffer of the encoded length */
115
+ VALUE out_value = rb_tainted_str_new(NULL, encoded_len);
116
+
117
+ base64_encode( RSTRING_PTR(out_value), val, len );
118
+
119
+ /* Is it a pure String conversion? Then we can directly send out_value to the user. */
120
+ if( this->comp.format == 0 && dec_func == pg_text_dec_string ){
121
+ PG_ENCODING_SET_NOCHECK( out_value, enc_idx );
122
+ return out_value;
123
+ }
124
+ if( this->comp.format == 1 && dec_func == pg_bin_dec_bytea ){
125
+ PG_ENCODING_SET_NOCHECK( out_value, rb_ascii8bit_encindex() );
126
+ return out_value;
127
+ }
128
+ out_value = dec_func(this->elem, RSTRING_PTR(out_value), encoded_len, tuple, field, enc_idx);
129
+
130
+ return out_value;
131
+ }
132
+
133
+ /*
134
+ * Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
135
+ *
136
+ * This is a decoder class for conversion of PostgreSQL text output to
137
+ * to Ruby String object. The output value will have the character encoding
138
+ * set with PG::Connection#internal_encoding= .
139
+ *
140
+ */
141
+
142
+ void
143
+ init_pg_binary_decoder()
144
+ {
145
+ /* This module encapsulates all decoder classes with binary input format */
146
+ rb_mPG_BinaryDecoder = rb_define_module_under( rb_mPG, "BinaryDecoder" );
147
+
148
+ /* Make RDoc aware of the decoder classes... */
149
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Boolean", rb_cPG_SimpleDecoder ); */
150
+ pg_define_coder( "Boolean", pg_bin_dec_boolean, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
151
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Integer", rb_cPG_SimpleDecoder ); */
152
+ pg_define_coder( "Integer", pg_bin_dec_integer, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
153
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Float", rb_cPG_SimpleDecoder ); */
154
+ pg_define_coder( "Float", pg_bin_dec_float, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
155
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "String", rb_cPG_SimpleDecoder ); */
156
+ pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
157
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
158
+ pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
159
+
160
+ /* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
161
+ pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
162
+ }
@@ -0,0 +1,162 @@
1
+ /*
2
+ * pg_column_map.c - PG::ColumnMap class extension
3
+ * $Id: pg_binary_encoder.c,v 72168db5fb7b 2015/11/04 16:13:42 lars $
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+ #include "util.h"
9
+ #ifdef HAVE_INTTYPES_H
10
+ #include <inttypes.h>
11
+ #endif
12
+
13
+ VALUE rb_mPG_BinaryEncoder;
14
+
15
+
16
+ /*
17
+ * Document-class: PG::BinaryEncoder::Boolean < PG::SimpleEncoder
18
+ *
19
+ * This is the encoder class for the PostgreSQL boolean type.
20
+ *
21
+ * It accepts true and false. Other values will raise an exception.
22
+ *
23
+ */
24
+ static int
25
+ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
26
+ {
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" );
33
+ }
34
+ if(out) *out = mybool;
35
+ return 1;
36
+ }
37
+
38
+ /*
39
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
40
+ *
41
+ * This is the encoder class for the PostgreSQL int2 type.
42
+ *
43
+ * Non-Number values are expected to have method +to_i+ defined.
44
+ *
45
+ */
46
+ static int
47
+ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
48
+ {
49
+ if(out){
50
+ write_nbo16(NUM2INT(*intermediate), out);
51
+ }else{
52
+ *intermediate = pg_obj_to_i(value);
53
+ }
54
+ return 2;
55
+ }
56
+
57
+ /*
58
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
59
+ *
60
+ * This is the encoder class for the PostgreSQL int4 type.
61
+ *
62
+ * Non-Number values are expected to have method +to_i+ defined.
63
+ *
64
+ */
65
+ static int
66
+ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
67
+ {
68
+ if(out){
69
+ write_nbo32(NUM2LONG(*intermediate), out);
70
+ }else{
71
+ *intermediate = pg_obj_to_i(value);
72
+ }
73
+ return 4;
74
+ }
75
+
76
+ /*
77
+ * Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
78
+ *
79
+ * This is the encoder class for the PostgreSQL int8 type.
80
+ *
81
+ * Non-Number values are expected to have method +to_i+ defined.
82
+ *
83
+ */
84
+ static int
85
+ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
86
+ {
87
+ if(out){
88
+ write_nbo64(NUM2LL(*intermediate), out);
89
+ }else{
90
+ *intermediate = pg_obj_to_i(value);
91
+ }
92
+ return 8;
93
+ }
94
+
95
+ /*
96
+ * Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
97
+ *
98
+ * This is an encoder class for conversion of base64 encoded data
99
+ * to it's binary representation.
100
+ *
101
+ */
102
+ static int
103
+ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate)
104
+ {
105
+ int strlen;
106
+ VALUE subint;
107
+ t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
108
+ t_pg_coder_enc_func enc_func = pg_coder_enc_func(this->elem);
109
+
110
+ if(out){
111
+ /* Second encoder pass, if required */
112
+ strlen = enc_func(this->elem, value, out, intermediate);
113
+ strlen = base64_decode( out, out, strlen );
114
+
115
+ return strlen;
116
+ } else {
117
+ /* First encoder pass */
118
+ strlen = enc_func(this->elem, value, NULL, &subint);
119
+
120
+ if( strlen == -1 ){
121
+ /* Encoded string is returned in subint */
122
+ VALUE out_str;
123
+
124
+ strlen = RSTRING_LENINT(subint);
125
+ out_str = rb_str_new(NULL, BASE64_DECODED_SIZE(strlen));
126
+
127
+ strlen = base64_decode( RSTRING_PTR(out_str), RSTRING_PTR(subint), strlen);
128
+ rb_str_set_len( out_str, strlen );
129
+ *intermediate = out_str;
130
+
131
+ return -1;
132
+ } else {
133
+ *intermediate = subint;
134
+
135
+ return BASE64_DECODED_SIZE(strlen);
136
+ }
137
+ }
138
+ }
139
+
140
+ void
141
+ init_pg_binary_encoder()
142
+ {
143
+ /* This module encapsulates all encoder classes with binary output format */
144
+ rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
145
+
146
+ /* Make RDoc aware of the encoder classes... */
147
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Boolean", rb_cPG_SimpleEncoder ); */
148
+ pg_define_coder( "Boolean", pg_bin_enc_boolean, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
149
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int2", rb_cPG_SimpleEncoder ); */
150
+ pg_define_coder( "Int2", pg_bin_enc_int2, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
151
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int4", rb_cPG_SimpleEncoder ); */
152
+ pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
153
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
154
+ pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
155
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
156
+ pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
157
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
158
+ pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
159
+
160
+ /* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
161
+ pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
162
+ }