pg 1.5.4 → 1.6.2
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/{History.md → CHANGELOG.md} +117 -4
- data/Gemfile +12 -3
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +4 -4
- data/README.md +60 -20
- data/Rakefile +95 -14
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +4 -5
- data/ext/errorcodes.txt +2 -5
- data/ext/extconf.rb +191 -15
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +17 -6
- data/ext/pg.h +9 -9
- data/ext/pg_binary_decoder.c +153 -1
- data/ext/pg_binary_encoder.c +213 -10
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +54 -5
- data/ext/pg_connection.c +409 -167
- data/ext/pg_copy_coder.c +19 -15
- data/ext/pg_record_coder.c +7 -7
- data/ext/pg_result.c +17 -19
- data/ext/pg_text_decoder.c +5 -2
- data/ext/pg_text_encoder.c +39 -20
- data/ext/pg_tuple.c +7 -7
- data/ext/pg_type_map.c +4 -2
- 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 +2 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/pg_util.c +2 -2
- data/ext/pg_util.h +2 -2
- data/lib/pg/basic_type_map_for_queries.rb +15 -7
- data/lib/pg/basic_type_registry.rb +16 -4
- data/lib/pg/cancel_connection.rb +53 -0
- data/lib/pg/coder.rb +4 -2
- data/lib/pg/connection.rb +310 -167
- data/lib/pg/exceptions.rb +6 -0
- data/lib/pg/text_decoder/date.rb +3 -0
- data/lib/pg/text_decoder/json.rb +3 -0
- data/lib/pg/text_encoder/date.rb +1 -0
- data/lib/pg/text_encoder/inet.rb +3 -0
- data/lib/pg/text_encoder/json.rb +3 -0
- data/lib/pg/version.rb +2 -1
- data/lib/pg.rb +156 -120
- data/misc/glibc/Dockerfile +20 -0
- data/misc/glibc/docker-compose.yml +9 -0
- data/misc/glibc/glibc_spec.rb +5 -0
- data/misc/yugabyte/Dockerfile +9 -0
- data/misc/yugabyte/docker-compose.yml +28 -0
- data/misc/yugabyte/pg-test.rb +45 -0
- data/pg.gemspec +8 -4
- data/ports/patches/krb5/1.22.1/0001-Allow-static-linking-krb5-library.patch +30 -0
- data/ports/patches/krb5/1.22.1/0002-unknown-command-line-option-on-clang.patch +12 -0
- data/ports/patches/openssl/3.5.2/0001-aarch64-mingw.patch +21 -0
- data/ports/patches/postgresql/17.6/0001-Use-workaround-of-__builtin_setjmp-only-on-MINGW-on-.patch +42 -0
- data/ports/patches/postgresql/17.6/0001-libpq-Process-buffered-SSL-read-bytes-to-support-rec.patch +52 -0
- data/rakelib/pg_gem_helper.rb +64 -0
- data.tar.gz.sig +0 -0
- metadata +49 -47
- metadata.gz.sig +0 -0
- data/.appveyor.yml +0 -42
- data/.gems +0 -6
- data/.gemtest +0 -0
- data/.github/workflows/binary-gems.yml +0 -117
- data/.github/workflows/source-gem.yml +0 -141
- data/.gitignore +0 -22
- data/.hgsigs +0 -34
- data/.hgtags +0 -41
- data/.irbrc +0 -23
- data/.pryrc +0 -23
- data/.tm_properties +0 -21
- data/.travis.yml +0 -49
- data/Manifest.txt +0 -72
- data/Rakefile.cross +0 -298
- data/translation/.po4a-version +0 -7
- data/translation/po/all.pot +0 -936
- data/translation/po/ja.po +0 -1036
- data/translation/po4a.cfg +0 -12
data/ext/pg_type_map_by_column.c
CHANGED
@@ -54,6 +54,7 @@ pg_tmbc_fit_to_query( VALUE self, VALUE params )
|
|
54
54
|
t_tmbc *this = RTYPEDDATA_DATA( self );
|
55
55
|
t_typemap *default_tm;
|
56
56
|
|
57
|
+
Check_Type(params, T_ARRAY);
|
57
58
|
nfields = (int)RARRAY_LEN( params );
|
58
59
|
if ( this->nfields != nfields ) {
|
59
60
|
rb_raise( rb_eArgError, "number of result fields (%d) does not match number of mapped columns (%d)",
|
@@ -228,7 +229,7 @@ static const rb_data_type_t pg_tmbc_type = {
|
|
228
229
|
pg_tmbc_mark,
|
229
230
|
pg_tmbc_free,
|
230
231
|
pg_tmbc_memsize,
|
231
|
-
|
232
|
+
pg_tmbc_compact,
|
232
233
|
},
|
233
234
|
&pg_typemap_type,
|
234
235
|
0,
|
data/ext/pg_type_map_by_oid.c
CHANGED
@@ -190,7 +190,7 @@ static const rb_data_type_t pg_tmbo_type = {
|
|
190
190
|
pg_tmbo_mark,
|
191
191
|
RUBY_TYPED_DEFAULT_FREE,
|
192
192
|
pg_tmbo_memsize,
|
193
|
-
|
193
|
+
pg_tmbo_compact,
|
194
194
|
},
|
195
195
|
&pg_typemap_type,
|
196
196
|
0,
|
@@ -315,6 +315,8 @@ pg_tmbo_coders( VALUE self )
|
|
315
315
|
* The type map will do Hash lookups for each result value, if the number of rows
|
316
316
|
* is below or equal +number+.
|
317
317
|
*
|
318
|
+
* Default is 10.
|
319
|
+
*
|
318
320
|
*/
|
319
321
|
static VALUE
|
320
322
|
pg_tmbo_max_rows_for_online_lookup_set( VALUE self, VALUE value )
|
data/ext/pg_type_map_in_ruby.c
CHANGED
data/ext/pg_util.c
CHANGED
@@ -15,7 +15,7 @@ static const char base64_encode_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijk
|
|
15
15
|
* in-place (with _out_ == _in_).
|
16
16
|
*/
|
17
17
|
void
|
18
|
-
|
18
|
+
rbpg_base64_encode( char *out, const char *in, int len)
|
19
19
|
{
|
20
20
|
const unsigned char *in_ptr = (const unsigned char *)in + len;
|
21
21
|
char *out_ptr = out + BASE64_ENCODED_SIZE(len);
|
@@ -72,7 +72,7 @@ static const unsigned char base64_decode_table[] =
|
|
72
72
|
* It is possible to decode a string in-place (with _out_ == _in_).
|
73
73
|
*/
|
74
74
|
int
|
75
|
-
|
75
|
+
rbpg_base64_decode( char *out, const char *in, unsigned int len)
|
76
76
|
{
|
77
77
|
unsigned char a, b, c, d;
|
78
78
|
const unsigned char *in_ptr = (const unsigned char *)in;
|
data/ext/pg_util.h
CHANGED
@@ -57,8 +57,8 @@
|
|
57
57
|
#define BASE64_ENCODED_SIZE(strlen) (((strlen) + 2) / 3 * 4)
|
58
58
|
#define BASE64_DECODED_SIZE(base64len) (((base64len) + 3) / 4 * 3)
|
59
59
|
|
60
|
-
void
|
61
|
-
int
|
60
|
+
void rbpg_base64_encode( char *out, const char *in, int len);
|
61
|
+
int rbpg_base64_decode( char *out, const char *in, unsigned int len);
|
62
62
|
|
63
63
|
int rbpg_strncasecmp(const char *s1, const char *s2, size_t n);
|
64
64
|
|
@@ -53,14 +53,18 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
53
53
|
@coder_maps = build_coder_maps(connection_or_coder_maps, registry: registry)
|
54
54
|
@array_encoders_by_klass = array_encoders_by_klass
|
55
55
|
@encode_array_as = :array
|
56
|
-
@if_undefined = if_undefined ||
|
56
|
+
@if_undefined = if_undefined || UndefinedDefault
|
57
57
|
init_encoders
|
58
58
|
end
|
59
59
|
|
60
|
-
|
61
|
-
|
60
|
+
class UndefinedDefault
|
61
|
+
def self.call(oid_name, format)
|
62
|
+
raise UndefinedEncoder, "no encoder defined for type #{oid_name.inspect} format #{format}"
|
63
|
+
end
|
62
64
|
end
|
63
65
|
|
66
|
+
private_constant :UndefinedDefault
|
67
|
+
|
64
68
|
# Change the mechanism that is used to encode ruby array values
|
65
69
|
#
|
66
70
|
# Possible values:
|
@@ -166,6 +170,12 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
166
170
|
@textarray_encoder
|
167
171
|
end
|
168
172
|
|
173
|
+
begin
|
174
|
+
PG.require_bigdecimal_without_warning
|
175
|
+
has_bigdecimal = true
|
176
|
+
rescue LoadError
|
177
|
+
end
|
178
|
+
|
169
179
|
DEFAULT_TYPE_MAP = PG.make_shareable({
|
170
180
|
TrueClass => [1, 'bool', 'bool'],
|
171
181
|
FalseClass => [1, 'bool', 'bool'],
|
@@ -173,7 +183,6 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
173
183
|
# to unnecessary type conversions on server side.
|
174
184
|
Integer => [0, 'int8'],
|
175
185
|
Float => [0, 'float8'],
|
176
|
-
BigDecimal => [0, 'numeric'],
|
177
186
|
Time => [0, 'timestamptz'],
|
178
187
|
# We use text format and no type OID for IPAddr, because setting the OID can lead
|
179
188
|
# to unnecessary inet/cidr conversions on the server side.
|
@@ -181,7 +190,7 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
181
190
|
Hash => [0, 'json'],
|
182
191
|
Array => :get_array_type,
|
183
192
|
BinaryData => [1, 'bytea'],
|
184
|
-
})
|
193
|
+
}.merge(has_bigdecimal ? {BigDecimal => [0, 'numeric']} : {}))
|
185
194
|
private_constant :DEFAULT_TYPE_MAP
|
186
195
|
|
187
196
|
DEFAULT_ARRAY_TYPE_MAP = PG.make_shareable({
|
@@ -190,9 +199,8 @@ class PG::BasicTypeMapForQueries < PG::TypeMapByClass
|
|
190
199
|
Integer => [0, '_int8'],
|
191
200
|
String => [0, '_text'],
|
192
201
|
Float => [0, '_float8'],
|
193
|
-
BigDecimal => [0, '_numeric'],
|
194
202
|
Time => [0, '_timestamptz'],
|
195
203
|
IPAddr => [0, '_inet'],
|
196
|
-
})
|
204
|
+
}.merge(has_bigdecimal ? {BigDecimal => [0, '_numeric']} : {}))
|
197
205
|
private_constant :DEFAULT_ARRAY_TYPE_MAP
|
198
206
|
end
|
@@ -127,8 +127,8 @@ class PG::BasicTypeRegistry
|
|
127
127
|
@maps = [
|
128
128
|
[0, :encoder, PG::TextEncoder::Array],
|
129
129
|
[0, :decoder, PG::TextDecoder::Array],
|
130
|
-
[1, :encoder,
|
131
|
-
[1, :decoder,
|
130
|
+
[1, :encoder, PG::BinaryEncoder::Array],
|
131
|
+
[1, :decoder, PG::BinaryDecoder::Array],
|
132
132
|
].inject([]) do |h, (format, direction, arraycoder)|
|
133
133
|
coders = registry.coders_for(format, direction) || {}
|
134
134
|
h[format] ||= {}
|
@@ -171,7 +171,14 @@ class PG::BasicTypeRegistry
|
|
171
171
|
include Checker
|
172
172
|
|
173
173
|
def initialize
|
174
|
-
#
|
174
|
+
# @coders_by_name has a content of
|
175
|
+
# Array< Hash< Symbol: Hash< String: Coder > > >
|
176
|
+
#
|
177
|
+
# The layers are:
|
178
|
+
# * index of Array is 0 (text) and 1 (binary)
|
179
|
+
# * Symbol key in the middle Hash is :encoder and :decoder
|
180
|
+
# * String key in the inner Hash corresponds to the `typname` column in the table pg_type
|
181
|
+
# * Coder value in the inner Hash is the associated coder object
|
175
182
|
@coders_by_name = []
|
176
183
|
end
|
177
184
|
|
@@ -225,7 +232,11 @@ class PG::BasicTypeRegistry
|
|
225
232
|
alias_type 0, 'int8', 'int2'
|
226
233
|
alias_type 0, 'oid', 'int2'
|
227
234
|
|
228
|
-
|
235
|
+
begin
|
236
|
+
PG.require_bigdecimal_without_warning
|
237
|
+
register_type 0, 'numeric', PG::TextEncoder::Numeric, PG::TextDecoder::Numeric
|
238
|
+
rescue LoadError
|
239
|
+
end
|
229
240
|
register_type 0, 'text', PG::TextEncoder::String, PG::TextDecoder::String
|
230
241
|
alias_type 0, 'varchar', 'text'
|
231
242
|
alias_type 0, 'char', 'text'
|
@@ -267,6 +278,7 @@ class PG::BasicTypeRegistry
|
|
267
278
|
register_type 0, 'inet', PG::TextEncoder::Inet, PG::TextDecoder::Inet
|
268
279
|
alias_type 0, 'cidr', 'inet'
|
269
280
|
|
281
|
+
register_type 0, 'record', PG::TextEncoder::Record, PG::TextDecoder::Record
|
270
282
|
|
271
283
|
|
272
284
|
register_type 1, 'int2', PG::BinaryEncoder::Int2, PG::BinaryDecoder::Integer
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pg' unless defined?( PG )
|
5
|
+
|
6
|
+
if defined?(PG::CancelConnection)
|
7
|
+
class PG::CancelConnection
|
8
|
+
include PG::Connection::Pollable
|
9
|
+
|
10
|
+
alias c_initialize initialize
|
11
|
+
|
12
|
+
def initialize(conn)
|
13
|
+
c_initialize(conn)
|
14
|
+
|
15
|
+
# A cancel connection is always to one destination server only.
|
16
|
+
# Prepare conninfo_hash with just enough information to allow a shared polling_loop.
|
17
|
+
@host = conn.host
|
18
|
+
@hostaddr = conn.hostaddr
|
19
|
+
@port = conn.port
|
20
|
+
|
21
|
+
@conninfo_hash = {
|
22
|
+
host: @host,
|
23
|
+
hostaddr: @hostaddr,
|
24
|
+
port: @port.to_s,
|
25
|
+
connect_timeout: conn.conninfo_hash[:connect_timeout],
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# call-seq:
|
30
|
+
# conn.cancel
|
31
|
+
#
|
32
|
+
# Requests that the server abandons processing of the current command in a blocking manner.
|
33
|
+
#
|
34
|
+
# If the cancel request wasn't successfully dispatched an error message is raised.
|
35
|
+
#
|
36
|
+
# Successful dispatch of the cancellation is no guarantee that the request will have any effect, however.
|
37
|
+
# If the cancellation is effective, the command being canceled will terminate early and raises an error.
|
38
|
+
# If the cancellation fails (say, because the server was already done processing the command), then there will be no visible result at all.
|
39
|
+
#
|
40
|
+
def cancel
|
41
|
+
start
|
42
|
+
polling_loop(:poll)
|
43
|
+
end
|
44
|
+
alias async_cancel cancel
|
45
|
+
|
46
|
+
# These private methods are there to allow a shared polling_loop.
|
47
|
+
private
|
48
|
+
attr_reader :host
|
49
|
+
attr_reader :hostaddr
|
50
|
+
attr_reader :port
|
51
|
+
attr_reader :conninfo_hash
|
52
|
+
end
|
53
|
+
end
|
data/lib/pg/coder.rb
CHANGED
@@ -72,16 +72,18 @@ module PG
|
|
72
72
|
|
73
73
|
class CompositeCoder < Coder
|
74
74
|
def to_h
|
75
|
-
{ **super,
|
75
|
+
h = { **super,
|
76
76
|
elements_type: elements_type,
|
77
77
|
needs_quotation: needs_quotation?,
|
78
78
|
delimiter: delimiter,
|
79
79
|
}
|
80
|
+
h[:dimensions] = dimensions if dimensions # Write only when set, for Marshal compat with pg<1.6
|
81
|
+
h
|
80
82
|
end
|
81
83
|
|
82
84
|
def inspect
|
83
85
|
str = super
|
84
|
-
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation"
|
86
|
+
str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation#{dimensions && " #{dimensions} dimensions"}"
|
85
87
|
str
|
86
88
|
end
|
87
89
|
end
|