pg 1.0.0-x64-mingw32 → 1.1.0.pre20180730144600-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +52 -0
- data/README.rdoc +11 -0
- data/Rakefile +2 -2
- data/Rakefile.cross +4 -4
- data/ext/errorcodes.rb +1 -1
- data/ext/extconf.rb +2 -0
- data/ext/pg.c +3 -2
- data/ext/pg.h +33 -5
- data/ext/pg_binary_decoder.c +69 -6
- data/ext/pg_binary_encoder.c +1 -1
- data/ext/pg_coder.c +52 -3
- data/ext/pg_connection.c +290 -103
- data/ext/pg_copy_coder.c +10 -5
- data/ext/pg_result.c +339 -113
- data/ext/pg_text_decoder.c +597 -37
- data/ext/pg_text_encoder.c +1 -1
- data/ext/pg_tuple.c +540 -0
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +1 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/util.c +6 -6
- data/ext/util.h +2 -2
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/2.1/pg_ext.so +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/2.4/pg_ext.so +0 -0
- data/lib/2.5/pg_ext.so +0 -0
- data/lib/libpq.dll +0 -0
- data/lib/pg.rb +5 -3
- data/lib/pg/basic_type_mapping.rb +40 -7
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +20 -1
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +1 -1
- data/lib/pg/text_decoder.rb +19 -23
- data/lib/pg/text_encoder.rb +35 -1
- data/lib/pg/type_map_by_column.rb +1 -1
- data/spec/helpers.rb +39 -7
- data/spec/pg/basic_type_mapping_spec.rb +230 -27
- data/spec/pg/connection_spec.rb +116 -77
- data/spec/pg/result_spec.rb +46 -11
- data/spec/pg/type_map_by_class_spec.rb +1 -1
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_map_by_oid_spec.rb +1 -1
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +177 -11
- data/spec/pg_spec.rb +1 -1
- metadata +25 -29
- metadata.gz.sig +0 -0
data/History.rdoc
CHANGED
@@ -1,3 +1,54 @@
|
|
1
|
+
== v2.0.0 - far from release -
|
2
|
+
|
3
|
+
Removed:
|
4
|
+
- Removed query method variants deprecated in pg-1.1.0.
|
5
|
+
|
6
|
+
|
7
|
+
== v1.1.0 [YYYY-MM-DD] Michael Granger <ged@FaerieMUD.org>
|
8
|
+
|
9
|
+
Deprecated:
|
10
|
+
- Forwarding conn.exec to conn.exec_params is deprecated.
|
11
|
+
- Forwarding conn.exec_params to conn.exec is deprecated.
|
12
|
+
- Forwarding conn.async_exec to conn.async_exec_params.
|
13
|
+
- Forwarding conn.send_query to conn.send_query_params is deprecated.
|
14
|
+
- Forwarding conn.async_exec_params to conn.async_exec is deprecated.
|
15
|
+
|
16
|
+
PG::Connection enhancements:
|
17
|
+
- Provide PG::Connection#sync_* and PG::Connection#async_* query methods for explicit calling syncronous or asynchronous libpq API.
|
18
|
+
- Make PG::Connection#exec and siblings switchable between sync and async API per PG::Connection.async_api= and change the default to async flavors.
|
19
|
+
- Add async flavors of exec_params, prepare, exec_prepared, describe_prepared and describe_portal.
|
20
|
+
They are identical to their syncronous counterpart, but make use of PostgreSQL's async API.
|
21
|
+
- Replace `rb_thread_fd_select()` by faster `rb_wait_for_single_fd()` in `conn.block` and `conn.async_exec` .
|
22
|
+
- Add PG::Connection#discard_results .
|
23
|
+
|
24
|
+
Result retrieval enhancements:
|
25
|
+
- Add PG::Result#tuple_values to retrieve all field values of a row as array.
|
26
|
+
- Add PG::Tuple, PG::Result#tuple_values and PG::Result#stream_each_tuple .
|
27
|
+
PG::Tuple offers a way to lazy cast result values.
|
28
|
+
- Estimate PG::Result size allocated by libpq and notify the garbage collector about it when running on Ruby-2.4 or newer.
|
29
|
+
- Make the estimated PG::Result size available to ObjectSpace.memsize_of(result) .
|
30
|
+
|
31
|
+
Type cast enhancements:
|
32
|
+
- Replace Ruby code by a faster C implementation of the SimpleDecoder's timestamp decode functions. github #20
|
33
|
+
- Interpret years with up to 7 digists and BC dates by timestamp decoder.
|
34
|
+
- Add text timestamp decoders for UTC vs. local timezone variations.
|
35
|
+
- Add text timestamp encoders for UTC timezone.
|
36
|
+
- Add decoders for binary timestamps: PG::BinaryDecoder::Timestamp and variations.
|
37
|
+
- Add PG::Coder#flags accessor to allow modifications of de- respectively encoder behaviour.
|
38
|
+
- Add a flag to raise TypeError for invalid input values to PG::TextDecoder::Array .
|
39
|
+
- Add a text decoder for inet/cidr written in C.
|
40
|
+
- Add a numeric decoder written in C.
|
41
|
+
- Ensure input text is zero terminated for text format in PG::Coder#decode .
|
42
|
+
|
43
|
+
Source code enhancements:
|
44
|
+
- Fix headers and permission bits of various repository files.
|
45
|
+
|
46
|
+
Bugfixes:
|
47
|
+
- Properly decode array with prepended dimensions. #272
|
48
|
+
For now dimension decorations are ignored, but a correct Array is returned.
|
49
|
+
- Array-Decoder: Avoid leaking memory when an Exception is raised while parsing. Fixes #279
|
50
|
+
|
51
|
+
|
1
52
|
== v1.0.0 [2018-01-10] Michael Granger <ged@FaerieMUD.org>
|
2
53
|
|
3
54
|
Deprecated:
|
@@ -7,6 +58,7 @@ Deprecated:
|
|
7
58
|
Removed:
|
8
59
|
- Remove compatibility code for Ruby < 2.0 and PostgreSQL < 9.2.
|
9
60
|
- Remove partial compatibility with Rubinius.
|
61
|
+
- Remove top-level constants PGconn, PGresult, and PGError.
|
10
62
|
|
11
63
|
Enhancements:
|
12
64
|
- Update error codes to PostgreSQL-10
|
data/README.rdoc
CHANGED
@@ -44,6 +44,17 @@ It usually work with earlier versions of Ruby/PostgreSQL as well, but those are
|
|
44
44
|
not regularly tested.
|
45
45
|
|
46
46
|
|
47
|
+
== Versioning
|
48
|
+
|
49
|
+
We tag and release gems according to the {Semantic Versioning}[http://semver.org/] principle.
|
50
|
+
|
51
|
+
As a result of this policy, you can (and should) specify a dependency on this gem using the {Pessimistic Version Constraint}[http://guides.rubygems.org/patterns/#pessimistic-version-constraint] with two digits of precision.
|
52
|
+
|
53
|
+
For example:
|
54
|
+
|
55
|
+
spec.add_dependency 'pg', '~> 1.0'
|
56
|
+
|
57
|
+
|
47
58
|
== How To Install
|
48
59
|
|
49
60
|
Install via RubyGems:
|
data/Rakefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# -*- rake -*-
|
2
2
|
|
3
3
|
require 'rbconfig'
|
4
4
|
require 'pathname'
|
@@ -184,7 +184,7 @@ end
|
|
184
184
|
|
185
185
|
desc "Update list of server error codes"
|
186
186
|
task :update_error_codes do
|
187
|
-
URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/
|
187
|
+
URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/REL_10_4"
|
188
188
|
|
189
189
|
ERRORCODES_TXT = "ext/errorcodes.txt"
|
190
190
|
sh "wget #{URL_ERRORCODES_TXT.inspect} -O #{ERRORCODES_TXT.inspect} || curl #{URL_ERRORCODES_TXT.inspect} -o #{ERRORCODES_TXT.inspect}"
|
data/Rakefile.cross
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# -*- rake -*-
|
2
2
|
|
3
3
|
require 'uri'
|
4
4
|
require 'tempfile'
|
@@ -29,8 +29,8 @@ class CrossLibrary < OpenStruct
|
|
29
29
|
self.host_platform = toolchain
|
30
30
|
|
31
31
|
# Cross-compilation constants
|
32
|
-
self.openssl_version = ENV['OPENSSL_VERSION'] || '1.1.
|
33
|
-
self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '10.
|
32
|
+
self.openssl_version = ENV['OPENSSL_VERSION'] || '1.1.0h'
|
33
|
+
self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '10.4'
|
34
34
|
|
35
35
|
# Check if symlinks work in the current working directory.
|
36
36
|
# This fails, if rake-compiler-dock is running on a Windows box.
|
@@ -293,6 +293,6 @@ task 'gem:windows' => ['ChangeLog'] do
|
|
293
293
|
mkdir ~/.gem &&
|
294
294
|
(cp build/gem/gem-*.pem ~/.gem/ || true) &&
|
295
295
|
bundle install --local &&
|
296
|
-
rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0
|
296
|
+
rake cross native gem RUBY_CC_VERSION=2.5.0:2.4.0:2.3.0:2.2.2:2.1.6:2.0.0 MAKE="make -j`nproc`"
|
297
297
|
EOT
|
298
298
|
end
|
data/ext/errorcodes.rb
CHANGED
data/ext/extconf.rb
CHANGED
data/ext/pg.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*
|
2
2
|
* pg.c - Toplevel extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
* Author/s:
|
6
6
|
*
|
@@ -143,7 +143,7 @@ pg_find_or_create_johab(void)
|
|
143
143
|
|
144
144
|
enc_index = rb_define_dummy_encoding(aliases[0]);
|
145
145
|
for (i = 1; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
|
146
|
-
|
146
|
+
rb_enc_alias(aliases[i], aliases[0]);
|
147
147
|
}
|
148
148
|
return rb_enc_from_index(enc_index);
|
149
149
|
}
|
@@ -630,5 +630,6 @@ Init_pg_ext()
|
|
630
630
|
init_pg_binary_encoder();
|
631
631
|
init_pg_binary_decoder();
|
632
632
|
init_pg_copycoder();
|
633
|
+
init_pg_tuple();
|
633
634
|
}
|
634
635
|
|
data/ext/pg.h
CHANGED
@@ -22,7 +22,7 @@
|
|
22
22
|
#include "ruby/encoding.h"
|
23
23
|
|
24
24
|
/* exported by ruby-1.9.3+ but not declared */
|
25
|
-
extern int
|
25
|
+
extern int rb_enc_alias(const char *, const char *);
|
26
26
|
|
27
27
|
#define PG_ENCODING_SET_NOCHECK(obj,i) \
|
28
28
|
do { \
|
@@ -77,6 +77,10 @@ typedef long suseconds_t;
|
|
77
77
|
#define PG_MAX_COLUMNS 4000
|
78
78
|
#endif
|
79
79
|
|
80
|
+
#ifndef RARRAY_AREF
|
81
|
+
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
82
|
+
#endif
|
83
|
+
|
80
84
|
/* The data behind each PG::Connection object */
|
81
85
|
typedef struct {
|
82
86
|
PGconn *pgconn;
|
@@ -100,6 +104,11 @@ typedef struct {
|
|
100
104
|
/* Kind of PG::Coder object for casting COPY rows to ruby values */
|
101
105
|
VALUE decoder_for_get_copy_data;
|
102
106
|
|
107
|
+
/* The connection socket, used for rb_wait_for_single_fd() */
|
108
|
+
int socket;
|
109
|
+
|
110
|
+
/* enable/disable guessing size of PGresult's allocated memory */
|
111
|
+
int guess_result_memsize;
|
103
112
|
} t_pg_connection;
|
104
113
|
|
105
114
|
typedef struct pg_coder t_pg_coder;
|
@@ -130,9 +139,15 @@ typedef struct {
|
|
130
139
|
*/
|
131
140
|
int nfields;
|
132
141
|
|
142
|
+
/* Size of PGresult as published to ruby memory management. */
|
143
|
+
ssize_t result_size;
|
144
|
+
|
133
145
|
/* Prefilled tuple Hash with fnames[] as keys. */
|
134
146
|
VALUE tuple_hash;
|
135
147
|
|
148
|
+
/* Hash with fnames[] to field number mapping. */
|
149
|
+
VALUE field_map;
|
150
|
+
|
136
151
|
/* List of field names as frozen String objects.
|
137
152
|
* Only valid if nfields != -1
|
138
153
|
*/
|
@@ -141,7 +156,7 @@ typedef struct {
|
|
141
156
|
|
142
157
|
|
143
158
|
typedef int (* t_pg_coder_enc_func)(t_pg_coder *, VALUE, char *, VALUE *, int);
|
144
|
-
typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, char *, int, int, int, int);
|
159
|
+
typedef VALUE (* t_pg_coder_dec_func)(t_pg_coder *, const char *, int, int, int, int);
|
145
160
|
typedef VALUE (* t_pg_fit_to_result)(VALUE, VALUE);
|
146
161
|
typedef VALUE (* t_pg_fit_to_query)(VALUE, VALUE);
|
147
162
|
typedef int (* t_pg_fit_to_copy_get)(VALUE);
|
@@ -149,12 +164,23 @@ typedef VALUE (* t_pg_typecast_result)(t_typemap *, VALUE, int, int);
|
|
149
164
|
typedef t_pg_coder *(* t_pg_typecast_query_param)(t_typemap *, VALUE, int);
|
150
165
|
typedef VALUE (* t_pg_typecast_copy_get)( t_typemap *, VALUE, int, int, int );
|
151
166
|
|
167
|
+
#define PG_CODER_TIMESTAMP_DB_UTC 0x0
|
168
|
+
#define PG_CODER_TIMESTAMP_DB_LOCAL 0x1
|
169
|
+
#define PG_CODER_TIMESTAMP_APP_UTC 0x0
|
170
|
+
#define PG_CODER_TIMESTAMP_APP_LOCAL 0x2
|
171
|
+
#define PG_CODER_FORMAT_ERROR_MASK 0xc
|
172
|
+
#define PG_CODER_FORMAT_ERROR_TO_RAISE 0x4
|
173
|
+
#define PG_CODER_FORMAT_ERROR_TO_STRING 0x8
|
174
|
+
#define PG_CODER_FORMAT_ERROR_TO_PARTIAL 0xc
|
175
|
+
|
152
176
|
struct pg_coder {
|
153
177
|
t_pg_coder_enc_func enc_func;
|
154
178
|
t_pg_coder_dec_func dec_func;
|
155
179
|
VALUE coder_obj;
|
156
180
|
Oid oid;
|
157
181
|
int format;
|
182
|
+
/* OR-ed values out of PG_CODER_* */
|
183
|
+
int flags;
|
158
184
|
};
|
159
185
|
|
160
186
|
typedef struct {
|
@@ -253,9 +279,10 @@ void init_pg_text_encoder _(( void ));
|
|
253
279
|
void init_pg_text_decoder _(( void ));
|
254
280
|
void init_pg_binary_encoder _(( void ));
|
255
281
|
void init_pg_binary_decoder _(( void ));
|
282
|
+
void init_pg_tuple _(( void ));
|
256
283
|
VALUE lookup_error_class _(( const char * ));
|
257
|
-
VALUE pg_bin_dec_bytea _(( t_pg_coder*, char *, int, int, int, int ));
|
258
|
-
VALUE pg_text_dec_string _(( t_pg_coder*, char *, int, int, int, int ));
|
284
|
+
VALUE pg_bin_dec_bytea _(( t_pg_coder*, const char *, int, int, int, int ));
|
285
|
+
VALUE pg_text_dec_string _(( t_pg_coder*, const char *, int, int, int, int ));
|
259
286
|
int pg_coder_enc_to_s _(( t_pg_coder*, VALUE, char *, VALUE *, int));
|
260
287
|
int pg_text_enc_identifier _(( t_pg_coder*, VALUE, char *, VALUE *, int));
|
261
288
|
t_pg_coder_enc_func pg_coder_enc_func _(( t_pg_coder* ));
|
@@ -298,6 +325,7 @@ VALUE pg_new_result_autoclear _(( PGresult *, VALUE ));
|
|
298
325
|
PGresult* pgresult_get _(( VALUE ));
|
299
326
|
VALUE pg_result_check _(( VALUE ));
|
300
327
|
VALUE pg_result_clear _(( VALUE ));
|
328
|
+
VALUE pg_tuple_new _(( VALUE, int ));
|
301
329
|
|
302
330
|
/*
|
303
331
|
* Fetch the data pointer for the result object
|
@@ -305,7 +333,7 @@ VALUE pg_result_clear _(( VALUE ));
|
|
305
333
|
static inline t_pg_result *
|
306
334
|
pgresult_get_this( VALUE self )
|
307
335
|
{
|
308
|
-
t_pg_result *this =
|
336
|
+
t_pg_result *this = RTYPEDDATA_DATA(self);
|
309
337
|
|
310
338
|
if( this == NULL )
|
311
339
|
rb_raise(rb_ePGerror, "result has been cleared");
|
data/ext/pg_binary_decoder.c
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
/*
|
2
2
|
* pg_column_map.c - PG::ColumnMap class extension
|
3
|
-
* $Id
|
3
|
+
* $Id$
|
4
4
|
*
|
5
5
|
*/
|
6
6
|
|
7
|
+
#include "ruby/version.h"
|
7
8
|
#include "pg.h"
|
8
9
|
#include "util.h"
|
9
10
|
#ifdef HAVE_INTTYPES_H
|
@@ -21,7 +22,7 @@ VALUE rb_mPG_BinaryDecoder;
|
|
21
22
|
*
|
22
23
|
*/
|
23
24
|
static VALUE
|
24
|
-
pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
25
|
+
pg_bin_dec_boolean(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
25
26
|
{
|
26
27
|
if (len < 1) {
|
27
28
|
rb_raise( rb_eTypeError, "wrong data for binary boolean converter in tuple %d field %d", tuple, field);
|
@@ -37,7 +38,7 @@ pg_bin_dec_boolean(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
37
38
|
*
|
38
39
|
*/
|
39
40
|
static VALUE
|
40
|
-
pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
41
|
+
pg_bin_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
41
42
|
{
|
42
43
|
switch( len ){
|
43
44
|
case 2:
|
@@ -59,7 +60,7 @@ pg_bin_dec_integer(t_pg_coder *conv, char *val, int len, int tuple, int field, i
|
|
59
60
|
*
|
60
61
|
*/
|
61
62
|
static VALUE
|
62
|
-
pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
63
|
+
pg_bin_dec_float(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
63
64
|
{
|
64
65
|
union {
|
65
66
|
float f;
|
@@ -91,7 +92,7 @@ pg_bin_dec_float(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
91
92
|
*
|
92
93
|
*/
|
93
94
|
VALUE
|
94
|
-
pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
95
|
+
pg_bin_dec_bytea(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
95
96
|
{
|
96
97
|
VALUE ret;
|
97
98
|
ret = rb_tainted_str_new( val, len );
|
@@ -106,7 +107,7 @@ pg_bin_dec_bytea(t_pg_coder *conv, char *val, int len, int tuple, int field, int
|
|
106
107
|
*
|
107
108
|
*/
|
108
109
|
static VALUE
|
109
|
-
pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field, int enc_idx)
|
110
|
+
pg_bin_dec_to_base64(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
110
111
|
{
|
111
112
|
t_pg_composite_coder *this = (t_pg_composite_coder *)conv;
|
112
113
|
t_pg_coder_dec_func dec_func = pg_coder_dec_func(this->elem, this->comp.format);
|
@@ -130,6 +131,66 @@ pg_bin_dec_to_base64(t_pg_coder *conv, char *val, int len, int tuple, int field,
|
|
130
131
|
return out_value;
|
131
132
|
}
|
132
133
|
|
134
|
+
#define PG_INT64_MIN (-0x7FFFFFFFFFFFFFFFL - 1)
|
135
|
+
#define PG_INT64_MAX 0x7FFFFFFFFFFFFFFFL
|
136
|
+
|
137
|
+
/*
|
138
|
+
* Document-class: PG::BinaryDecoder::Timestamp < PG::SimpleDecoder
|
139
|
+
*
|
140
|
+
* This is a decoder class for conversion of PostgreSQL binary timestamps
|
141
|
+
* to Ruby Time objects.
|
142
|
+
*
|
143
|
+
* The following flags can be used to specify timezone interpretation:
|
144
|
+
* * +PG::Coder::TIMESTAMP_DB_UTC+ : Interpret timestamp as UTC time (default)
|
145
|
+
* * +PG::Coder::TIMESTAMP_DB_LOCAL+ : Interpret timestamp as local time
|
146
|
+
* * +PG::Coder::TIMESTAMP_APP_UTC+ : Return timestamp as UTC time (default)
|
147
|
+
* * +PG::Coder::TIMESTAMP_APP_LOCAL+ : Return timestamp as local time
|
148
|
+
*
|
149
|
+
* Example:
|
150
|
+
* deco = PG::BinaryDecoder::Timestamp.new(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
|
151
|
+
* deco.decode("\0"*8) # => 2000-01-01 01:00:00 +0100
|
152
|
+
*/
|
153
|
+
static VALUE
|
154
|
+
pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
155
|
+
{
|
156
|
+
int64_t timestamp;
|
157
|
+
struct timespec ts;
|
158
|
+
VALUE t;
|
159
|
+
|
160
|
+
if( len != sizeof(timestamp) ){
|
161
|
+
rb_raise( rb_eTypeError, "wrong data for timestamp converter in tuple %d field %d length %d", tuple, field, len);
|
162
|
+
}
|
163
|
+
|
164
|
+
timestamp = read_nbo64(val);
|
165
|
+
|
166
|
+
switch(timestamp){
|
167
|
+
case PG_INT64_MAX:
|
168
|
+
return rb_str_new2("infinity");
|
169
|
+
case PG_INT64_MIN:
|
170
|
+
return rb_str_new2("-infinity");
|
171
|
+
default:
|
172
|
+
/* PostgreSQL's timestamp is based on year 2000 and Ruby's time is based on 1970.
|
173
|
+
* Adjust the 30 years difference. */
|
174
|
+
ts.tv_sec = (timestamp / 1000000) + 10957L * 24L * 3600L;
|
175
|
+
ts.tv_nsec = (timestamp % 1000000) * 1000;
|
176
|
+
|
177
|
+
#if (RUBY_API_VERSION_MAJOR > 2 || (RUBY_API_VERSION_MAJOR == 2 && RUBY_API_VERSION_MINOR >= 3)) && defined(NEGATIVE_TIME_T)
|
178
|
+
/* Fast path for time conversion */
|
179
|
+
t = rb_time_timespec_new(&ts, conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL ? INT_MAX : INT_MAX-1);
|
180
|
+
#else
|
181
|
+
t = rb_funcall(rb_cTime, rb_intern("at"), 2, LL2NUM(ts.tv_sec), LL2NUM(ts.tv_nsec / 1000));
|
182
|
+
if( !(conv->flags & PG_CODER_TIMESTAMP_APP_LOCAL) ) {
|
183
|
+
t = rb_funcall(t, rb_intern("utc"), 0);
|
184
|
+
}
|
185
|
+
#endif
|
186
|
+
if( conv->flags & PG_CODER_TIMESTAMP_DB_LOCAL ) {
|
187
|
+
/* interpret it as local time */
|
188
|
+
t = rb_funcall(t, rb_intern("-"), 1, rb_funcall(t, rb_intern("utc_offset"), 0));
|
189
|
+
}
|
190
|
+
return t;
|
191
|
+
}
|
192
|
+
}
|
193
|
+
|
133
194
|
/*
|
134
195
|
* Document-class: PG::BinaryDecoder::String < PG::SimpleDecoder
|
135
196
|
*
|
@@ -156,6 +217,8 @@ init_pg_binary_decoder()
|
|
156
217
|
pg_define_coder( "String", pg_text_dec_string, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
157
218
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Bytea", rb_cPG_SimpleDecoder ); */
|
158
219
|
pg_define_coder( "Bytea", pg_bin_dec_bytea, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
220
|
+
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "Timestamp", rb_cPG_SimpleDecoder ); */
|
221
|
+
pg_define_coder( "Timestamp", pg_bin_dec_timestamp, rb_cPG_SimpleDecoder, rb_mPG_BinaryDecoder );
|
159
222
|
|
160
223
|
/* dummy = rb_define_class_under( rb_mPG_BinaryDecoder, "ToBase64", rb_cPG_CompositeDecoder ); */
|
161
224
|
pg_define_coder( "ToBase64", pg_bin_dec_to_base64, rb_cPG_CompositeDecoder, rb_mPG_BinaryDecoder );
|
data/ext/pg_binary_encoder.c
CHANGED
data/ext/pg_coder.c
CHANGED
@@ -38,6 +38,7 @@ pg_coder_init_encoder( VALUE self )
|
|
38
38
|
this->coder_obj = self;
|
39
39
|
this->oid = 0;
|
40
40
|
this->format = 0;
|
41
|
+
this->flags = 0;
|
41
42
|
rb_iv_set( self, "@name", Qnil );
|
42
43
|
}
|
43
44
|
|
@@ -56,6 +57,7 @@ pg_coder_init_decoder( VALUE self )
|
|
56
57
|
this->coder_obj = self;
|
57
58
|
this->oid = 0;
|
58
59
|
this->format = 0;
|
60
|
+
this->flags = 0;
|
59
61
|
rb_iv_set( self, "@name", Qnil );
|
60
62
|
}
|
61
63
|
|
@@ -192,7 +194,11 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
192
194
|
if( NIL_P(argv[0]) )
|
193
195
|
return Qnil;
|
194
196
|
|
195
|
-
|
197
|
+
if( this->format == 0 ){
|
198
|
+
val = StringValueCStr(argv[0]);
|
199
|
+
}else{
|
200
|
+
val = StringValuePtr(argv[0]);
|
201
|
+
}
|
196
202
|
if( !this->dec_func ){
|
197
203
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
198
204
|
}
|
@@ -265,6 +271,36 @@ pg_coder_format_get(VALUE self)
|
|
265
271
|
return INT2NUM(this->format);
|
266
272
|
}
|
267
273
|
|
274
|
+
/*
|
275
|
+
* call-seq:
|
276
|
+
* coder.flags = Integer
|
277
|
+
*
|
278
|
+
* Set coder specific bitwise OR-ed flags.
|
279
|
+
* See the particular en- or decoder description for available flags.
|
280
|
+
*
|
281
|
+
* The default is +0+.
|
282
|
+
*/
|
283
|
+
static VALUE
|
284
|
+
pg_coder_flags_set(VALUE self, VALUE flags)
|
285
|
+
{
|
286
|
+
t_pg_coder *this = DATA_PTR(self);
|
287
|
+
this->flags = NUM2INT(flags);
|
288
|
+
return flags;
|
289
|
+
}
|
290
|
+
|
291
|
+
/*
|
292
|
+
* call-seq:
|
293
|
+
* coder.flags -> Integer
|
294
|
+
*
|
295
|
+
* Get current bitwise OR-ed coder flags.
|
296
|
+
*/
|
297
|
+
static VALUE
|
298
|
+
pg_coder_flags_get(VALUE self)
|
299
|
+
{
|
300
|
+
t_pg_coder *this = DATA_PTR(self);
|
301
|
+
return INT2NUM(this->flags);
|
302
|
+
}
|
303
|
+
|
268
304
|
/*
|
269
305
|
* call-seq:
|
270
306
|
* coder.needs_quotation = Boolean
|
@@ -403,14 +439,14 @@ pg_coder_enc_func(t_pg_coder *this)
|
|
403
439
|
}
|
404
440
|
|
405
441
|
static VALUE
|
406
|
-
pg_text_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
442
|
+
pg_text_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
407
443
|
{
|
408
444
|
VALUE string = pg_text_dec_string(this, val, len, tuple, field, enc_idx);
|
409
445
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
410
446
|
}
|
411
447
|
|
412
448
|
static VALUE
|
413
|
-
pg_bin_dec_in_ruby(t_pg_coder *this, char *val, int len, int tuple, int field, int enc_idx)
|
449
|
+
pg_bin_dec_in_ruby(t_pg_coder *this, const char *val, int len, int tuple, int field, int enc_idx)
|
414
450
|
{
|
415
451
|
VALUE string = pg_bin_dec_bytea(this, val, len, tuple, field, enc_idx);
|
416
452
|
return rb_funcall( this->coder_obj, s_id_decode, 3, string, INT2NUM(tuple), INT2NUM(field) );
|
@@ -457,6 +493,19 @@ init_pg_coder()
|
|
457
493
|
rb_define_method( rb_cPG_Coder, "oid", pg_coder_oid_get, 0 );
|
458
494
|
rb_define_method( rb_cPG_Coder, "format=", pg_coder_format_set, 1 );
|
459
495
|
rb_define_method( rb_cPG_Coder, "format", pg_coder_format_get, 0 );
|
496
|
+
rb_define_method( rb_cPG_Coder, "flags=", pg_coder_flags_set, 1 );
|
497
|
+
rb_define_method( rb_cPG_Coder, "flags", pg_coder_flags_get, 0 );
|
498
|
+
|
499
|
+
/* define flags to be used with PG::Coder#flags= */
|
500
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_UTC", INT2NUM(PG_CODER_TIMESTAMP_DB_UTC));
|
501
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_DB_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_DB_LOCAL));
|
502
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_UTC", INT2NUM(PG_CODER_TIMESTAMP_APP_UTC));
|
503
|
+
rb_define_const( rb_cPG_Coder, "TIMESTAMP_APP_LOCAL", INT2NUM(PG_CODER_TIMESTAMP_APP_LOCAL));
|
504
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_MASK", INT2NUM(PG_CODER_FORMAT_ERROR_MASK));
|
505
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_RAISE", INT2NUM(PG_CODER_FORMAT_ERROR_TO_RAISE));
|
506
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_STRING", INT2NUM(PG_CODER_FORMAT_ERROR_TO_STRING));
|
507
|
+
rb_define_const( rb_cPG_Coder, "FORMAT_ERROR_TO_PARTIAL", INT2NUM(PG_CODER_FORMAT_ERROR_TO_PARTIAL));
|
508
|
+
|
460
509
|
/*
|
461
510
|
* Name of the coder or the corresponding data type.
|
462
511
|
*
|