pg 0.17.1 → 0.18.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|