pg 1.1.3 → 1.5.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/.appveyor.yml +42 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +117 -0
- data/.github/workflows/source-gem.yml +141 -0
- data/.gitignore +22 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.md +884 -0
- data/Manifest.txt +3 -3
- data/README-Windows.rdoc +4 -4
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +37 -137
- data/Rakefile.cross +62 -62
- data/certs/ged.pem +24 -0
- data/certs/larskanis-2022.pem +26 -0
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +80 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +22 -2
- data/ext/extconf.rb +105 -26
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +204 -152
- data/ext/pg.h +52 -21
- data/ext/pg_binary_decoder.c +100 -17
- data/ext/pg_binary_encoder.c +238 -13
- data/ext/pg_coder.c +109 -34
- data/ext/pg_connection.c +1383 -983
- data/ext/pg_copy_coder.c +356 -35
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +522 -0
- data/ext/pg_result.c +439 -172
- data/ext/pg_text_decoder.c +42 -18
- data/ext/pg_text_encoder.c +201 -56
- data/ext/pg_tuple.c +97 -66
- data/ext/pg_type_map.c +45 -11
- data/ext/pg_type_map_all_strings.c +21 -7
- data/ext/pg_type_map_by_class.c +59 -27
- data/ext/pg_type_map_by_column.c +80 -37
- data/ext/pg_type_map_by_mri_type.c +49 -20
- data/ext/pg_type_map_by_oid.c +62 -29
- data/ext/pg_type_map_in_ruby.c +56 -22
- data/ext/{util.c → pg_util.c} +7 -7
- data/lib/pg/basic_type_map_based_on_result.rb +67 -0
- data/lib/pg/basic_type_map_for_queries.rb +198 -0
- data/lib/pg/basic_type_map_for_results.rb +104 -0
- data/lib/pg/basic_type_registry.rb +299 -0
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +35 -12
- data/lib/pg/connection.rb +744 -84
- data/lib/pg/exceptions.rb +15 -1
- data/lib/pg/result.rb +13 -1
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/type_map_by_column.rb +2 -1
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +94 -39
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +34 -0
- data/rakelib/task_extension.rb +46 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +102 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data/translation/.po4a-version +7 -0
- data/translation/po/all.pot +936 -0
- data/translation/po/ja.po +1036 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +144 -222
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +0 -485
- data/README.ja.rdoc +0 -14
- data/README.rdoc +0 -178
- data/lib/pg/basic_type_mapping.rb +0 -459
- data/lib/pg/binary_decoder.rb +0 -22
- data/lib/pg/constants.rb +0 -11
- data/lib/pg/text_decoder.rb +0 -47
- data/lib/pg/text_encoder.rb +0 -69
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -381
- data/spec/pg/basic_type_mapping_spec.rb +0 -508
- data/spec/pg/connection_spec.rb +0 -1849
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -491
- data/spec/pg/tuple_spec.rb +0 -280
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -222
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -949
- data/spec/pg_spec.rb +0 -50
- /data/ext/{util.h → pg_util.h} +0 -0
data/ext/pg_binary_encoder.c
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
|
3
|
-
* $Id
|
|
3
|
+
* $Id$
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
#include "pg.h"
|
|
8
|
-
#include "
|
|
8
|
+
#include "pg_util.h"
|
|
9
9
|
#ifdef HAVE_INTTYPES_H
|
|
10
10
|
#include <inttypes.h>
|
|
11
11
|
#endif
|
|
12
12
|
|
|
13
13
|
VALUE rb_mPG_BinaryEncoder;
|
|
14
|
+
static ID s_id_year;
|
|
15
|
+
static ID s_id_month;
|
|
16
|
+
static ID s_id_day;
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
/*
|
|
@@ -25,11 +28,12 @@ static int
|
|
|
25
28
|
pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
26
29
|
{
|
|
27
30
|
char mybool;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
if (value == Qtrue) {
|
|
32
|
+
mybool = 1;
|
|
33
|
+
} else if (value == Qfalse) {
|
|
34
|
+
mybool = 0;
|
|
35
|
+
} else {
|
|
36
|
+
rb_raise( rb_eTypeError, "wrong data for binary boolean converter" );
|
|
33
37
|
}
|
|
34
38
|
if(out) *out = mybool;
|
|
35
39
|
return 1;
|
|
@@ -38,7 +42,7 @@ pg_bin_enc_boolean(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
|
38
42
|
/*
|
|
39
43
|
* Document-class: PG::BinaryEncoder::Int2 < PG::SimpleEncoder
|
|
40
44
|
*
|
|
41
|
-
* This is the encoder class for the PostgreSQL int2 type.
|
|
45
|
+
* This is the encoder class for the PostgreSQL +int2+ (alias +smallint+) type.
|
|
42
46
|
*
|
|
43
47
|
* Non-Number values are expected to have method +to_i+ defined.
|
|
44
48
|
*
|
|
@@ -55,9 +59,9 @@ pg_bin_enc_int2(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
/*
|
|
58
|
-
* Document-class: PG::BinaryEncoder::
|
|
62
|
+
* Document-class: PG::BinaryEncoder::Int4 < PG::SimpleEncoder
|
|
59
63
|
*
|
|
60
|
-
* This is the encoder class for the PostgreSQL int4 type.
|
|
64
|
+
* This is the encoder class for the PostgreSQL +int4+ (alias +integer+) type.
|
|
61
65
|
*
|
|
62
66
|
* Non-Number values are expected to have method +to_i+ defined.
|
|
63
67
|
*
|
|
@@ -74,9 +78,9 @@ pg_bin_enc_int4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
/*
|
|
77
|
-
* Document-class: PG::BinaryEncoder::
|
|
81
|
+
* Document-class: PG::BinaryEncoder::Int8 < PG::SimpleEncoder
|
|
78
82
|
*
|
|
79
|
-
* This is the encoder class for the PostgreSQL int8 type.
|
|
83
|
+
* This is the encoder class for the PostgreSQL +int8+ (alias +bigint+) type.
|
|
80
84
|
*
|
|
81
85
|
* Non-Number values are expected to have method +to_i+ defined.
|
|
82
86
|
*
|
|
@@ -92,6 +96,215 @@ pg_bin_enc_int8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, i
|
|
|
92
96
|
return 8;
|
|
93
97
|
}
|
|
94
98
|
|
|
99
|
+
/*
|
|
100
|
+
* Document-class: PG::BinaryEncoder::Float4 < PG::SimpleEncoder
|
|
101
|
+
*
|
|
102
|
+
* This is the binary encoder class for the PostgreSQL +float4+ type.
|
|
103
|
+
*
|
|
104
|
+
*/
|
|
105
|
+
static int
|
|
106
|
+
pg_bin_enc_float4(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
107
|
+
{
|
|
108
|
+
union {
|
|
109
|
+
float f;
|
|
110
|
+
int32_t i;
|
|
111
|
+
} swap4;
|
|
112
|
+
|
|
113
|
+
if(out){
|
|
114
|
+
swap4.f = NUM2DBL(*intermediate);
|
|
115
|
+
write_nbo32(swap4.i, out);
|
|
116
|
+
}else{
|
|
117
|
+
*intermediate = value;
|
|
118
|
+
}
|
|
119
|
+
return 4;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/*
|
|
123
|
+
* Document-class: PG::BinaryEncoder::Float8 < PG::SimpleEncoder
|
|
124
|
+
*
|
|
125
|
+
* This is the binary encoder class for the PostgreSQL +float8+ type.
|
|
126
|
+
*
|
|
127
|
+
*/
|
|
128
|
+
static int
|
|
129
|
+
pg_bin_enc_float8(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
130
|
+
{
|
|
131
|
+
union {
|
|
132
|
+
double f;
|
|
133
|
+
int64_t i;
|
|
134
|
+
} swap8;
|
|
135
|
+
|
|
136
|
+
if(out){
|
|
137
|
+
swap8.f = NUM2DBL(*intermediate);
|
|
138
|
+
write_nbo64(swap8.i, out);
|
|
139
|
+
}else{
|
|
140
|
+
*intermediate = value;
|
|
141
|
+
}
|
|
142
|
+
return 8;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
#define PG_INT32_MIN (-0x7FFFFFFF-1)
|
|
146
|
+
#define PG_INT32_MAX (0x7FFFFFFF)
|
|
147
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
|
148
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
|
149
|
+
|
|
150
|
+
/*
|
|
151
|
+
* Document-class: PG::BinaryEncoder::Timestamp < PG::SimpleEncoder
|
|
152
|
+
*
|
|
153
|
+
* This is a encoder class for conversion of Ruby Time objects to PostgreSQL binary timestamps.
|
|
154
|
+
*
|
|
155
|
+
* The following flags can be used to specify timezone interpretation:
|
|
156
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Send timestamp as UTC time (default)
|
|
157
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Send timestamp as local time (slower)
|
|
158
|
+
*
|
|
159
|
+
* Example:
|
|
160
|
+
* enco = PG::BinaryEncoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC)
|
|
161
|
+
* enco.encode(Time.utc(2000, 1, 1)) # => "\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
162
|
+
*
|
|
163
|
+
* String values are expected to contain a binary data with a length of 8 byte.
|
|
164
|
+
*
|
|
165
|
+
*/
|
|
166
|
+
static int
|
|
167
|
+
pg_bin_enc_timestamp(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
168
|
+
{
|
|
169
|
+
if(out){
|
|
170
|
+
int64_t timestamp;
|
|
171
|
+
struct timespec ts;
|
|
172
|
+
|
|
173
|
+
/* second call -> write data to *out */
|
|
174
|
+
switch(TYPE(*intermediate)){
|
|
175
|
+
case T_STRING:
|
|
176
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
177
|
+
case T_TRUE:
|
|
178
|
+
write_nbo64(PG_INT64_MAX, out);
|
|
179
|
+
return 8;
|
|
180
|
+
case T_FALSE:
|
|
181
|
+
write_nbo64(PG_INT64_MIN, out);
|
|
182
|
+
return 8;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
ts = rb_time_timespec(*intermediate);
|
|
186
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
|
187
|
+
* Adjust the 30 years difference. */
|
|
188
|
+
timestamp = (ts.tv_sec - 10957L * 24L * 3600L) * 1000000 + (ts.tv_nsec / 1000);
|
|
189
|
+
|
|
190
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
|
191
|
+
/* send as local time */
|
|
192
|
+
timestamp += NUM2LL(rb_funcall(*intermediate, rb_intern("utc_offset"), 0)) * 1000000;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
write_nbo64(timestamp, out);
|
|
196
|
+
}else{
|
|
197
|
+
/* first call -> determine the required length */
|
|
198
|
+
if(TYPE(value) == T_STRING){
|
|
199
|
+
char *pstr = RSTRING_PTR(value);
|
|
200
|
+
if(RSTRING_LEN(value) >= 1){
|
|
201
|
+
switch(pstr[0]) {
|
|
202
|
+
case 'I':
|
|
203
|
+
case 'i':
|
|
204
|
+
*intermediate = Qtrue;
|
|
205
|
+
return 8;
|
|
206
|
+
case '-':
|
|
207
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
|
208
|
+
*intermediate = Qfalse;
|
|
209
|
+
return 8;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
if( this->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
|
218
|
+
/* make a local time, so that utc_offset is set */
|
|
219
|
+
value = rb_funcall(value, rb_intern("getlocal"), 0);
|
|
220
|
+
}
|
|
221
|
+
*intermediate = value;
|
|
222
|
+
}
|
|
223
|
+
return 8;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
#define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
|
|
227
|
+
int
|
|
228
|
+
date2j(int year, int month, int day)
|
|
229
|
+
{
|
|
230
|
+
int julian;
|
|
231
|
+
int century;
|
|
232
|
+
|
|
233
|
+
if (month > 2)
|
|
234
|
+
{
|
|
235
|
+
month += 1;
|
|
236
|
+
year += 4800;
|
|
237
|
+
}
|
|
238
|
+
else
|
|
239
|
+
{
|
|
240
|
+
month += 13;
|
|
241
|
+
year += 4799;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
century = year / 100;
|
|
245
|
+
julian = year * 365 - 32167;
|
|
246
|
+
julian += year / 4 - century + century / 4;
|
|
247
|
+
julian += 7834 * month / 256 + day;
|
|
248
|
+
|
|
249
|
+
return julian;
|
|
250
|
+
} /* date2j() */
|
|
251
|
+
|
|
252
|
+
/*
|
|
253
|
+
* Document-class: PG::BinaryEncoder::Date < PG::SimpleEncoder
|
|
254
|
+
*
|
|
255
|
+
* This is a encoder class for conversion of Ruby Date objects to PostgreSQL binary date.
|
|
256
|
+
*
|
|
257
|
+
* String values are expected to contain a binary data with a length of 4 byte.
|
|
258
|
+
*
|
|
259
|
+
*/
|
|
260
|
+
static int
|
|
261
|
+
pg_bin_enc_date(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
|
262
|
+
{
|
|
263
|
+
if(out){
|
|
264
|
+
/* second call -> write data to *out */
|
|
265
|
+
switch(TYPE(*intermediate)){
|
|
266
|
+
case T_STRING:
|
|
267
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
268
|
+
case T_TRUE:
|
|
269
|
+
write_nbo32(PG_INT32_MAX, out);
|
|
270
|
+
return 4;
|
|
271
|
+
case T_FALSE:
|
|
272
|
+
write_nbo32(PG_INT32_MIN, out);
|
|
273
|
+
return 4;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
VALUE year = rb_funcall(value, s_id_year, 0);
|
|
277
|
+
VALUE month = rb_funcall(value, s_id_month, 0);
|
|
278
|
+
VALUE day = rb_funcall(value, s_id_day, 0);
|
|
279
|
+
int jday = date2j(NUM2INT(year), NUM2INT(month), NUM2INT(day)) - POSTGRES_EPOCH_JDATE;
|
|
280
|
+
write_nbo32(jday, out);
|
|
281
|
+
|
|
282
|
+
}else{
|
|
283
|
+
/* first call -> determine the required length */
|
|
284
|
+
if(TYPE(value) == T_STRING){
|
|
285
|
+
char *pstr = RSTRING_PTR(value);
|
|
286
|
+
if(RSTRING_LEN(value) >= 1){
|
|
287
|
+
switch(pstr[0]) {
|
|
288
|
+
case 'I':
|
|
289
|
+
case 'i':
|
|
290
|
+
*intermediate = Qtrue;
|
|
291
|
+
return 4;
|
|
292
|
+
case '-':
|
|
293
|
+
if (RSTRING_LEN(value) >= 2 && (pstr[1] == 'I' || pstr[1] == 'i')) {
|
|
294
|
+
*intermediate = Qfalse;
|
|
295
|
+
return 4;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
return pg_coder_enc_to_s(this, value, out, intermediate, enc_idx);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
*intermediate = value;
|
|
304
|
+
}
|
|
305
|
+
return 4;
|
|
306
|
+
}
|
|
307
|
+
|
|
95
308
|
/*
|
|
96
309
|
* Document-class: PG::BinaryEncoder::FromBase64 < PG::CompositeEncoder
|
|
97
310
|
*
|
|
@@ -138,8 +351,12 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
|
|
|
138
351
|
}
|
|
139
352
|
|
|
140
353
|
void
|
|
141
|
-
init_pg_binary_encoder()
|
|
354
|
+
init_pg_binary_encoder(void)
|
|
142
355
|
{
|
|
356
|
+
s_id_year = rb_intern("year");
|
|
357
|
+
s_id_month = rb_intern("month");
|
|
358
|
+
s_id_day = rb_intern("day");
|
|
359
|
+
|
|
143
360
|
/* This module encapsulates all encoder classes with binary output format */
|
|
144
361
|
rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
|
|
145
362
|
|
|
@@ -152,10 +369,18 @@ init_pg_binary_encoder()
|
|
|
152
369
|
pg_define_coder( "Int4", pg_bin_enc_int4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
153
370
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Int8", rb_cPG_SimpleEncoder ); */
|
|
154
371
|
pg_define_coder( "Int8", pg_bin_enc_int8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
372
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float4", rb_cPG_SimpleEncoder ); */
|
|
373
|
+
pg_define_coder( "Float4", pg_bin_enc_float4, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
374
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Float8", rb_cPG_SimpleEncoder ); */
|
|
375
|
+
pg_define_coder( "Float8", pg_bin_enc_float8, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
155
376
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "String", rb_cPG_SimpleEncoder ); */
|
|
156
377
|
pg_define_coder( "String", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
157
378
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Bytea", rb_cPG_SimpleEncoder ); */
|
|
158
379
|
pg_define_coder( "Bytea", pg_coder_enc_to_s, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
380
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Timestamp", rb_cPG_SimpleEncoder ); */
|
|
381
|
+
pg_define_coder( "Timestamp", pg_bin_enc_timestamp, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
382
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "Date", rb_cPG_SimpleEncoder ); */
|
|
383
|
+
pg_define_coder( "Date", pg_bin_enc_date, rb_cPG_SimpleEncoder, rb_mPG_BinaryEncoder );
|
|
159
384
|
|
|
160
385
|
/* dummy = rb_define_class_under( rb_mPG_BinaryEncoder, "FromBase64", rb_cPG_CompositeEncoder ); */
|
|
161
386
|
pg_define_coder( "FromBase64", pg_bin_enc_from_base64, rb_cPG_CompositeEncoder, rb_mPG_BinaryEncoder );
|
data/ext/pg_coder.c
CHANGED
|
@@ -26,16 +26,16 @@ pg_coder_allocate( VALUE klass )
|
|
|
26
26
|
void
|
|
27
27
|
pg_coder_init_encoder( VALUE self )
|
|
28
28
|
{
|
|
29
|
-
t_pg_coder *this =
|
|
29
|
+
t_pg_coder *this = RTYPEDDATA_DATA( self );
|
|
30
30
|
VALUE klass = rb_class_of(self);
|
|
31
31
|
if( rb_const_defined( klass, s_id_CFUNC ) ){
|
|
32
32
|
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
|
|
33
|
-
this->enc_func =
|
|
33
|
+
this->enc_func = RTYPEDDATA_DATA(cfunc);
|
|
34
34
|
} else {
|
|
35
35
|
this->enc_func = NULL;
|
|
36
36
|
}
|
|
37
37
|
this->dec_func = NULL;
|
|
38
|
-
this->coder_obj
|
|
38
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
|
39
39
|
this->oid = 0;
|
|
40
40
|
this->format = 0;
|
|
41
41
|
this->flags = 0;
|
|
@@ -45,36 +45,92 @@ pg_coder_init_encoder( VALUE self )
|
|
|
45
45
|
void
|
|
46
46
|
pg_coder_init_decoder( VALUE self )
|
|
47
47
|
{
|
|
48
|
-
t_pg_coder *this =
|
|
48
|
+
t_pg_coder *this = RTYPEDDATA_DATA( self );
|
|
49
49
|
VALUE klass = rb_class_of(self);
|
|
50
50
|
this->enc_func = NULL;
|
|
51
51
|
if( rb_const_defined( klass, s_id_CFUNC ) ){
|
|
52
52
|
VALUE cfunc = rb_const_get( klass, s_id_CFUNC );
|
|
53
|
-
this->dec_func =
|
|
53
|
+
this->dec_func = RTYPEDDATA_DATA(cfunc);
|
|
54
54
|
} else {
|
|
55
55
|
this->dec_func = NULL;
|
|
56
56
|
}
|
|
57
|
-
this->coder_obj
|
|
57
|
+
RB_OBJ_WRITE(self, &this->coder_obj, self);
|
|
58
58
|
this->oid = 0;
|
|
59
59
|
this->format = 0;
|
|
60
60
|
this->flags = 0;
|
|
61
61
|
rb_iv_set( self, "@name", Qnil );
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
static size_t
|
|
65
|
+
pg_coder_memsize(const void *_this)
|
|
66
|
+
{
|
|
67
|
+
const t_pg_coder *this = (const t_pg_coder *)_this;
|
|
68
|
+
return sizeof(*this);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static size_t
|
|
72
|
+
pg_composite_coder_memsize(const void *_this)
|
|
73
|
+
{
|
|
74
|
+
const t_pg_composite_coder *this = (const t_pg_composite_coder *)_this;
|
|
75
|
+
return sizeof(*this);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
void
|
|
79
|
+
pg_coder_compact(void *_this)
|
|
80
|
+
{
|
|
81
|
+
t_pg_coder *this = (t_pg_coder *)_this;
|
|
82
|
+
pg_gc_location(this->coder_obj);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
static void
|
|
86
|
+
pg_composite_coder_compact(void *_this)
|
|
87
|
+
{
|
|
88
|
+
t_pg_composite_coder *this = (t_pg_composite_coder *)_this;
|
|
89
|
+
pg_coder_compact(&this->comp);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const rb_data_type_t pg_coder_type = {
|
|
93
|
+
"PG::Coder",
|
|
94
|
+
{
|
|
95
|
+
(RUBY_DATA_FUNC) NULL,
|
|
96
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
97
|
+
pg_coder_memsize,
|
|
98
|
+
pg_compact_callback(pg_coder_compact),
|
|
99
|
+
},
|
|
100
|
+
0,
|
|
101
|
+
0,
|
|
102
|
+
// IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
|
|
103
|
+
// macro to update VALUE references, as to trigger write barriers.
|
|
104
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
105
|
+
};
|
|
106
|
+
|
|
64
107
|
static VALUE
|
|
65
108
|
pg_simple_encoder_allocate( VALUE klass )
|
|
66
109
|
{
|
|
67
110
|
t_pg_coder *this;
|
|
68
|
-
VALUE self =
|
|
111
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
|
69
112
|
pg_coder_init_encoder( self );
|
|
70
113
|
return self;
|
|
71
114
|
}
|
|
72
115
|
|
|
116
|
+
static const rb_data_type_t pg_composite_coder_type = {
|
|
117
|
+
"PG::CompositeCoder",
|
|
118
|
+
{
|
|
119
|
+
(RUBY_DATA_FUNC) NULL,
|
|
120
|
+
RUBY_TYPED_DEFAULT_FREE,
|
|
121
|
+
pg_composite_coder_memsize,
|
|
122
|
+
pg_compact_callback(pg_composite_coder_compact),
|
|
123
|
+
},
|
|
124
|
+
&pg_coder_type,
|
|
125
|
+
0,
|
|
126
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
127
|
+
};
|
|
128
|
+
|
|
73
129
|
static VALUE
|
|
74
130
|
pg_composite_encoder_allocate( VALUE klass )
|
|
75
131
|
{
|
|
76
132
|
t_pg_composite_coder *this;
|
|
77
|
-
VALUE self =
|
|
133
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
|
78
134
|
pg_coder_init_encoder( self );
|
|
79
135
|
this->elem = NULL;
|
|
80
136
|
this->needs_quotation = 1;
|
|
@@ -87,7 +143,7 @@ static VALUE
|
|
|
87
143
|
pg_simple_decoder_allocate( VALUE klass )
|
|
88
144
|
{
|
|
89
145
|
t_pg_coder *this;
|
|
90
|
-
VALUE self =
|
|
146
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
|
91
147
|
pg_coder_init_decoder( self );
|
|
92
148
|
return self;
|
|
93
149
|
}
|
|
@@ -96,7 +152,7 @@ static VALUE
|
|
|
96
152
|
pg_composite_decoder_allocate( VALUE klass )
|
|
97
153
|
{
|
|
98
154
|
t_pg_composite_coder *this;
|
|
99
|
-
VALUE self =
|
|
155
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
|
100
156
|
pg_coder_init_decoder( self );
|
|
101
157
|
this->elem = NULL;
|
|
102
158
|
this->needs_quotation = 1;
|
|
@@ -123,7 +179,7 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
|
|
123
179
|
VALUE value;
|
|
124
180
|
int len, len2;
|
|
125
181
|
int enc_idx;
|
|
126
|
-
t_pg_coder *this =
|
|
182
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
127
183
|
|
|
128
184
|
if(argc < 1 || argc > 2){
|
|
129
185
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
|
|
@@ -145,7 +201,6 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
|
|
145
201
|
|
|
146
202
|
if( len == -1 ){
|
|
147
203
|
/* The intermediate value is a String that can be used directly. */
|
|
148
|
-
OBJ_INFECT(intermediate, value);
|
|
149
204
|
return intermediate;
|
|
150
205
|
}
|
|
151
206
|
|
|
@@ -157,7 +212,6 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
|
|
157
212
|
rb_obj_classname( self ), len, len2 );
|
|
158
213
|
}
|
|
159
214
|
rb_str_set_len( res, len2 );
|
|
160
|
-
OBJ_INFECT(res, value);
|
|
161
215
|
|
|
162
216
|
RB_GC_GUARD(intermediate);
|
|
163
217
|
|
|
@@ -182,7 +236,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
182
236
|
int tuple = -1;
|
|
183
237
|
int field = -1;
|
|
184
238
|
VALUE res;
|
|
185
|
-
t_pg_coder *this =
|
|
239
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
186
240
|
|
|
187
241
|
if(argc < 1 || argc > 3){
|
|
188
242
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
|
|
@@ -203,8 +257,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
203
257
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
|
204
258
|
}
|
|
205
259
|
|
|
206
|
-
res = this->dec_func(this, val,
|
|
207
|
-
OBJ_INFECT(res, argv[0]);
|
|
260
|
+
res = this->dec_func(this, val, RSTRING_LENINT(argv[0]), tuple, field, ENCODING_GET(argv[0]));
|
|
208
261
|
|
|
209
262
|
return res;
|
|
210
263
|
}
|
|
@@ -221,7 +274,8 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
|
221
274
|
static VALUE
|
|
222
275
|
pg_coder_oid_set(VALUE self, VALUE oid)
|
|
223
276
|
{
|
|
224
|
-
t_pg_coder *this =
|
|
277
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
278
|
+
rb_check_frozen(self);
|
|
225
279
|
this->oid = NUM2UINT(oid);
|
|
226
280
|
return oid;
|
|
227
281
|
}
|
|
@@ -236,7 +290,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
|
|
|
236
290
|
static VALUE
|
|
237
291
|
pg_coder_oid_get(VALUE self)
|
|
238
292
|
{
|
|
239
|
-
t_pg_coder *this =
|
|
293
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
240
294
|
return UINT2NUM(this->oid);
|
|
241
295
|
}
|
|
242
296
|
|
|
@@ -252,7 +306,8 @@ pg_coder_oid_get(VALUE self)
|
|
|
252
306
|
static VALUE
|
|
253
307
|
pg_coder_format_set(VALUE self, VALUE format)
|
|
254
308
|
{
|
|
255
|
-
t_pg_coder *this =
|
|
309
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
310
|
+
rb_check_frozen(self);
|
|
256
311
|
this->format = NUM2INT(format);
|
|
257
312
|
return format;
|
|
258
313
|
}
|
|
@@ -267,7 +322,7 @@ pg_coder_format_set(VALUE self, VALUE format)
|
|
|
267
322
|
static VALUE
|
|
268
323
|
pg_coder_format_get(VALUE self)
|
|
269
324
|
{
|
|
270
|
-
t_pg_coder *this =
|
|
325
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
271
326
|
return INT2NUM(this->format);
|
|
272
327
|
}
|
|
273
328
|
|
|
@@ -283,7 +338,8 @@ pg_coder_format_get(VALUE self)
|
|
|
283
338
|
static VALUE
|
|
284
339
|
pg_coder_flags_set(VALUE self, VALUE flags)
|
|
285
340
|
{
|
|
286
|
-
t_pg_coder *this =
|
|
341
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
342
|
+
rb_check_frozen(self);
|
|
287
343
|
this->flags = NUM2INT(flags);
|
|
288
344
|
return flags;
|
|
289
345
|
}
|
|
@@ -297,7 +353,7 @@ pg_coder_flags_set(VALUE self, VALUE flags)
|
|
|
297
353
|
static VALUE
|
|
298
354
|
pg_coder_flags_get(VALUE self)
|
|
299
355
|
{
|
|
300
|
-
t_pg_coder *this =
|
|
356
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
|
301
357
|
return INT2NUM(this->flags);
|
|
302
358
|
}
|
|
303
359
|
|
|
@@ -314,7 +370,8 @@ pg_coder_flags_get(VALUE self)
|
|
|
314
370
|
static VALUE
|
|
315
371
|
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
|
316
372
|
{
|
|
317
|
-
t_pg_composite_coder *this =
|
|
373
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
374
|
+
rb_check_frozen(self);
|
|
318
375
|
this->needs_quotation = RTEST(needs_quotation);
|
|
319
376
|
return needs_quotation;
|
|
320
377
|
}
|
|
@@ -329,7 +386,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
|
|
329
386
|
static VALUE
|
|
330
387
|
pg_coder_needs_quotation_get(VALUE self)
|
|
331
388
|
{
|
|
332
|
-
t_pg_composite_coder *this =
|
|
389
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
333
390
|
return this->needs_quotation ? Qtrue : Qfalse;
|
|
334
391
|
}
|
|
335
392
|
|
|
@@ -344,7 +401,8 @@ pg_coder_needs_quotation_get(VALUE self)
|
|
|
344
401
|
static VALUE
|
|
345
402
|
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
|
346
403
|
{
|
|
347
|
-
t_pg_composite_coder *this =
|
|
404
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
405
|
+
rb_check_frozen(self);
|
|
348
406
|
StringValue(delimiter);
|
|
349
407
|
if(RSTRING_LEN(delimiter) != 1)
|
|
350
408
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
|
@@ -361,7 +419,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
|
|
361
419
|
static VALUE
|
|
362
420
|
pg_coder_delimiter_get(VALUE self)
|
|
363
421
|
{
|
|
364
|
-
t_pg_composite_coder *this =
|
|
422
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
|
365
423
|
return rb_str_new(&this->delimiter, 1);
|
|
366
424
|
}
|
|
367
425
|
|
|
@@ -377,12 +435,13 @@ pg_coder_delimiter_get(VALUE self)
|
|
|
377
435
|
static VALUE
|
|
378
436
|
pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
379
437
|
{
|
|
380
|
-
t_pg_composite_coder *this =
|
|
438
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
|
|
381
439
|
|
|
440
|
+
rb_check_frozen(self);
|
|
382
441
|
if ( NIL_P(elem_type) ){
|
|
383
442
|
this->elem = NULL;
|
|
384
443
|
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
|
|
385
|
-
this->elem =
|
|
444
|
+
this->elem = RTYPEDDATA_DATA( elem_type );
|
|
386
445
|
} else {
|
|
387
446
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
|
|
388
447
|
rb_obj_classname( elem_type ) );
|
|
@@ -392,17 +451,35 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
|
392
451
|
return elem_type;
|
|
393
452
|
}
|
|
394
453
|
|
|
395
|
-
|
|
454
|
+
static const rb_data_type_t pg_coder_cfunc_type = {
|
|
455
|
+
"PG::Coder::CFUNC",
|
|
456
|
+
{
|
|
457
|
+
(RUBY_DATA_FUNC)NULL,
|
|
458
|
+
(RUBY_DATA_FUNC)NULL,
|
|
459
|
+
(size_t (*)(const void *))NULL,
|
|
460
|
+
},
|
|
461
|
+
0,
|
|
462
|
+
0,
|
|
463
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
VALUE
|
|
396
467
|
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
|
397
468
|
{
|
|
398
|
-
VALUE cfunc_obj =
|
|
469
|
+
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
|
|
399
470
|
VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
|
|
400
471
|
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
|
|
401
472
|
rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
|
|
402
473
|
|
|
403
|
-
|
|
474
|
+
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_TextEncoder )
|
|
475
|
+
rb_define_method( coder_klass, "encode", pg_coder_encode, -1 );
|
|
476
|
+
if( nsp==rb_mPG_BinaryDecoder || nsp==rb_mPG_TextDecoder )
|
|
477
|
+
rb_define_method( coder_klass, "decode", pg_coder_decode, -1 );
|
|
478
|
+
|
|
479
|
+
rb_define_const( coder_klass, "CFUNC", rb_obj_freeze(cfunc_obj) );
|
|
404
480
|
|
|
405
481
|
RB_GC_GUARD(cfunc_obj);
|
|
482
|
+
return coder_klass;
|
|
406
483
|
}
|
|
407
484
|
|
|
408
485
|
|
|
@@ -469,7 +546,7 @@ pg_coder_dec_func(t_pg_coder *this, int binary)
|
|
|
469
546
|
|
|
470
547
|
|
|
471
548
|
void
|
|
472
|
-
init_pg_coder()
|
|
549
|
+
init_pg_coder(void)
|
|
473
550
|
{
|
|
474
551
|
s_id_encode = rb_intern("encode");
|
|
475
552
|
s_id_decode = rb_intern("decode");
|
|
@@ -512,8 +589,6 @@ init_pg_coder()
|
|
|
512
589
|
* This accessor is only used in PG::Coder#inspect .
|
|
513
590
|
*/
|
|
514
591
|
rb_define_attr( rb_cPG_Coder, "name", 1, 1 );
|
|
515
|
-
rb_define_method( rb_cPG_Coder, "encode", pg_coder_encode, -1 );
|
|
516
|
-
rb_define_method( rb_cPG_Coder, "decode", pg_coder_decode, -1 );
|
|
517
592
|
|
|
518
593
|
/* Document-class: PG::SimpleCoder < PG::Coder */
|
|
519
594
|
rb_cPG_SimpleCoder = rb_define_class_under( rb_mPG, "SimpleCoder", rb_cPG_Coder );
|