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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/ChangeLog +2407 -2
- data/History.rdoc +68 -0
- data/Manifest.txt +29 -1
- data/README-Windows.rdoc +15 -26
- data/README.rdoc +52 -2
- data/Rakefile +56 -18
- data/Rakefile.cross +77 -49
- data/ext/extconf.rb +33 -26
- data/ext/pg.c +142 -21
- data/ext/pg.h +242 -6
- data/ext/pg_binary_decoder.c +162 -0
- data/ext/pg_binary_encoder.c +162 -0
- data/ext/pg_coder.c +479 -0
- data/ext/pg_connection.c +858 -553
- data/ext/pg_copy_coder.c +561 -0
- data/ext/pg_errors.c +6 -0
- data/ext/pg_result.c +479 -128
- data/ext/pg_text_decoder.c +421 -0
- data/ext/pg_text_encoder.c +663 -0
- data/ext/pg_type_map.c +159 -0
- data/ext/pg_type_map_all_strings.c +116 -0
- data/ext/pg_type_map_by_class.c +239 -0
- data/ext/pg_type_map_by_column.c +312 -0
- data/ext/pg_type_map_by_mri_type.c +284 -0
- data/ext/pg_type_map_by_oid.c +355 -0
- data/ext/pg_type_map_in_ruby.c +299 -0
- data/ext/util.c +149 -0
- data/ext/util.h +65 -0
- data/lib/pg/basic_type_mapping.rb +399 -0
- data/lib/pg/coder.rb +83 -0
- data/lib/pg/connection.rb +81 -29
- data/lib/pg/result.rb +13 -3
- data/lib/pg/text_decoder.rb +44 -0
- data/lib/pg/text_encoder.rb +27 -0
- data/lib/pg/type_map_by_column.rb +15 -0
- data/lib/pg.rb +12 -2
- data/spec/{lib/helpers.rb → helpers.rb} +101 -39
- data/spec/pg/basic_type_mapping_spec.rb +251 -0
- data/spec/pg/connection_spec.rb +516 -218
- data/spec/pg/result_spec.rb +216 -112
- data/spec/pg/type_map_by_class_spec.rb +138 -0
- data/spec/pg/type_map_by_column_spec.rb +222 -0
- data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
- data/spec/pg/type_map_by_oid_spec.rb +149 -0
- data/spec/pg/type_map_in_ruby_spec.rb +164 -0
- data/spec/pg/type_map_spec.rb +22 -0
- data/spec/pg/type_spec.rb +697 -0
- data/spec/pg_spec.rb +24 -18
- data.tar.gz.sig +0 -0
- metadata +111 -45
- 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
|
+
}
|