pg 1.5.6 → 1.5.9
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/Gemfile +3 -0
- data/History.md +35 -4
- data/Rakefile +1 -1
- data/Rakefile.cross +12 -8
- data/ext/errorcodes.def +4 -5
- data/ext/errorcodes.txt +2 -5
- data/ext/extconf.rb +3 -0
- data/ext/pg.c +1 -1
- data/ext/pg_binary_decoder.c +2 -0
- data/ext/pg_connection.c +23 -13
- data/ext/pg_copy_coder.c +10 -6
- data/ext/pg_record_coder.c +6 -6
- data/ext/pg_result.c +2 -2
- data/ext/pg_text_decoder.c +4 -1
- data/ext/pg_text_encoder.c +17 -11
- data/lib/pg/basic_type_map_for_queries.rb +1 -1
- data/lib/pg/basic_type_registry.rb +10 -2
- data/lib/pg/connection.rb +18 -7
- 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 +1 -1
- data/lib/pg.rb +10 -0
- data/pg.gemspec +3 -1
- data.tar.gz.sig +2 -3
- metadata +2 -14
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0abb6cbfa5134825baaaa3cab5bbb2d88a5092559331239ccb977c24579d27d
|
4
|
+
data.tar.gz: 53d6fd115d923b9654b2928791309d290a87f01275a13f3489025d673ba967ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c7b1c92f223b4250fd56d37bbfa94dadf19d9e03518e7a3426bb19800745f031ab133a3d8921ec2f63045762e46bbfe7ac5a01f0144c4eb3d5b3ad8cf2f1197d
|
7
|
+
data.tar.gz: 3fd53f91bfc2880da42fddcc5ae6a9334c419025636e0d1626b533da7fa62a6f87942629ed6c24c1183002295dcbdf56a33c96af2323e3a9fb0396bcb68e673e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/Gemfile
CHANGED
@@ -11,7 +11,10 @@ group :development, :test do
|
|
11
11
|
gem "rake-compiler-dock", "~> 1.0"
|
12
12
|
gem "rdoc", "~> 6.4"
|
13
13
|
gem "rspec", "~> 3.5"
|
14
|
+
gem "ostruct", "~> 0.5" # for Rakefile.cross
|
14
15
|
# "bigdecimal" is a gem on ruby-3.4+ and it's optional for ruby-pg.
|
15
16
|
# Specs should succeed without it, but 4 examples are then excluded.
|
17
|
+
# With bigdecimal commented out here, corresponding tests are omitted on ruby-3.4+ but are executed on ruby < 3.4.
|
18
|
+
# That way we can check both situations in CI.
|
16
19
|
# gem "bigdecimal", "~> 3.0"
|
17
20
|
end
|
data/History.md
CHANGED
@@ -1,3 +1,34 @@
|
|
1
|
+
## v1.5.9 [2024-10-24] Lars Kanis <lars@greiz-reinsdorf.de>
|
2
|
+
|
3
|
+
- Enable thread safety in static OpenSSL build for Windows. [#595](https://github.com/ged/ruby-pg/pull/595)
|
4
|
+
- Remove raising `conect_timeout` from 1 to 2 seconds. [#590](https://github.com/ged/ruby-pg/pull/590)
|
5
|
+
- Fix binary copy_data in Ractor context. [#594](https://github.com/ged/ruby-pg/pull/594)
|
6
|
+
- Exclude CI files and hidden files from built gem. [#591](https://github.com/ged/ruby-pg/pull/591)
|
7
|
+
This is to simplify security inspection.
|
8
|
+
- Update error classes to PostgreSQL-17.
|
9
|
+
- Update Windows fat binary gem to OpenSSL-3.4.0 and PostgreSQL-17.0.
|
10
|
+
|
11
|
+
|
12
|
+
## v1.5.8 [2024-09-06] Lars Kanis <lars@greiz-reinsdorf.de>
|
13
|
+
|
14
|
+
- Fix host list duplication every time conn.reset is used. [#586](https://github.com/ged/ruby-pg/pull/586)
|
15
|
+
- Add default decoder for anonymous record types to BasicTypeRegistry [#579](https://github.com/ged/ruby-pg/pull/579)
|
16
|
+
- Update Windows fat binary gem to OpenSSL-3.3.2 and PostgreSQL-16.4.
|
17
|
+
|
18
|
+
|
19
|
+
## v1.5.7 [2024-07-28] Lars Kanis <lars@greiz-reinsdorf.de>
|
20
|
+
|
21
|
+
- Remove deprecated use of fptr->fd.[#562](https://github.com/ged/ruby-pg/pull/562)
|
22
|
+
Direct access is disallowed since ruby-3.4.
|
23
|
+
- Make `pgconn_connect_poll` close the socket prior to calling `PQconnectPoll`. [#564](https://github.com/ged/ruby-pg/pull/564)
|
24
|
+
This could result in an exception while connecting when used multi threaded.
|
25
|
+
- Fix several typos and improve spelling in documentation and code. [#566](https://github.com/ged/ruby-pg/pull/566)
|
26
|
+
- Add missing PG::RollbackTransaction as an option to exit conn.transaction. [#560](https://github.com/ged/ruby-pg/pull/560)
|
27
|
+
Usage like in rails: https://api.rubyonrails.org/classes/ActiveRecord/Rollback.html
|
28
|
+
- Don't print a warning when bigdecimal is required on ruby-3.4+ [#574](https://github.com/ged/ruby-pg/pull/574)
|
29
|
+
- Update Windows fat binary gem to OpenSSL-3.3.1 and PostgreSQL-16.3.
|
30
|
+
|
31
|
+
|
1
32
|
## v1.5.6 [2024-03-01] Lars Kanis <lars@greiz-reinsdorf.de>
|
2
33
|
|
3
34
|
- Renew address resolution (DNS) in conn.reset. [#558](https://github.com/ged/ruby-pg/pull/558)
|
@@ -92,7 +123,7 @@ Removed:
|
|
92
123
|
Repository:
|
93
124
|
|
94
125
|
- `rake test` tries to find PostgreSQL server commands by pg_config [#503](https://github.com/ged/ruby-pg/pull/503)
|
95
|
-
So there's no need to set the PATH
|
126
|
+
So there's no need to set the PATH manually any longer.
|
96
127
|
|
97
128
|
|
98
129
|
## v1.4.6 [2023-02-26] Lars Kanis <lars@greiz-reinsdorf.de>
|
@@ -161,7 +192,7 @@ Added:
|
|
161
192
|
Bugfixes:
|
162
193
|
|
163
194
|
- Try IPv6 and IPv4 addresses, if DNS resolves to both. [#452](https://github.com/ged/ruby-pg/pull/452)
|
164
|
-
- Re-add block-call semantics to PG::Connection.new
|
195
|
+
- Re-add block-call semantics to PG::Connection.new accidentally removed in pg-1.3.0. [#454](https://github.com/ged/ruby-pg/pull/454)
|
165
196
|
- Handle client error after all data consumed in #copy_data for output. [#455](https://github.com/ged/ruby-pg/pull/455)
|
166
197
|
- Avoid spurious keyword argument warning on Ruby 2.7. [#456](https://github.com/ged/ruby-pg/pull/456)
|
167
198
|
- Change connection setup to respect connect_timeout parameter. [#459](https://github.com/ged/ruby-pg/pull/459)
|
@@ -200,7 +231,7 @@ Bugfixes:
|
|
200
231
|
|
201
232
|
- Don't leak IO in case of connection errors. [#439](https://github.com/ged/ruby-pg/pull/439)
|
202
233
|
Previously it was kept open until the PG::Connection was garbage collected.
|
203
|
-
- Fix a performance
|
234
|
+
- Fix a performance regression in conn.get_result noticed in single row mode. [#442](https://github.com/ged/ruby-pg/pull/442)
|
204
235
|
- Fix occasional error Errno::EBADF (Bad file descriptor) while connecting. [#444](https://github.com/ged/ruby-pg/pull/444)
|
205
236
|
- Fix compatibility of res.stream_each* methods with Fiber.scheduler. [#446](https://github.com/ged/ruby-pg/pull/446)
|
206
237
|
- Remove FL_TEST and FL_SET, which are MRI-internal. [#437](https://github.com/ged/ruby-pg/pull/437)
|
@@ -286,7 +317,7 @@ Type cast enhancements:
|
|
286
317
|
- Add PG::BasicTypeMapForQueries::BinaryData for encoding of bytea columns. [#348](https://github.com/ged/ruby-pg/pull/348)
|
287
318
|
- Reduce time to build coder maps and permit to reuse them for several type maps per PG::BasicTypeRegistry::CoderMapsBundle.new(conn) . [#376](https://github.com/ged/ruby-pg/pull/376)
|
288
319
|
- Make BasicTypeRegistry a class and use a global default instance of it.
|
289
|
-
Now a local type registry can be
|
320
|
+
Now a local type registry can be instantiated and given to the type map, to avoid changing shared global states.
|
290
321
|
- Allow PG::BasicTypeMapForQueries to take a Proc as callback for undefined types.
|
291
322
|
|
292
323
|
Other Enhancements:
|
data/Rakefile
CHANGED
@@ -94,7 +94,7 @@ end
|
|
94
94
|
|
95
95
|
desc "Update list of server error codes"
|
96
96
|
task :update_error_codes do
|
97
|
-
URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/
|
97
|
+
URL_ERRORCODES_TXT = "http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob_plain;f=src/backend/utils/errcodes.txt;hb=refs/tags/REL_17_0"
|
98
98
|
|
99
99
|
ERRORCODES_TXT = "ext/errorcodes.txt"
|
100
100
|
sh "wget #{URL_ERRORCODES_TXT.inspect} -O #{ERRORCODES_TXT.inspect} || curl #{URL_ERRORCODES_TXT.inspect} -o #{ERRORCODES_TXT.inspect}"
|
data/Rakefile.cross
CHANGED
@@ -31,8 +31,8 @@ class CrossLibrary < OpenStruct
|
|
31
31
|
self.host_platform = toolchain
|
32
32
|
|
33
33
|
# Cross-compilation constants
|
34
|
-
self.openssl_version = ENV['OPENSSL_VERSION'] || '3.
|
35
|
-
self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '
|
34
|
+
self.openssl_version = ENV['OPENSSL_VERSION'] || '3.4.0'
|
35
|
+
self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '17.0'
|
36
36
|
|
37
37
|
# Check if symlinks work in the current working directory.
|
38
38
|
# This fails, if rake-compiler-dock is running on a Windows box.
|
@@ -52,9 +52,8 @@ class CrossLibrary < OpenStruct
|
|
52
52
|
|
53
53
|
# Static OpenSSL build vars
|
54
54
|
self.static_openssl_builddir = static_builddir + "openssl-#{openssl_version}"
|
55
|
-
|
56
55
|
self.openssl_source_uri =
|
57
|
-
URI( "
|
56
|
+
URI( "https://github.com/openssl/openssl/releases/download/openssl-#{openssl_version}/openssl-#{openssl_version}.tar.gz" )
|
58
57
|
self.openssl_tarball = static_sourcesdir + File.basename( openssl_source_uri.path )
|
59
58
|
self.openssl_makefile = static_openssl_builddir + 'Makefile'
|
60
59
|
|
@@ -119,7 +118,7 @@ class CrossLibrary < OpenStruct
|
|
119
118
|
self.cmd_prelude = [
|
120
119
|
"env",
|
121
120
|
"CROSS_COMPILE=#{host_platform}-",
|
122
|
-
"CFLAGS=-DDSO_WIN32",
|
121
|
+
"CFLAGS=-DDSO_WIN32 -DOPENSSL_THREADS",
|
123
122
|
]
|
124
123
|
|
125
124
|
|
@@ -127,7 +126,7 @@ class CrossLibrary < OpenStruct
|
|
127
126
|
file openssl_makefile => static_openssl_builddir do |t|
|
128
127
|
chdir( static_openssl_builddir ) do
|
129
128
|
cmd = cmd_prelude.dup
|
130
|
-
cmd << "./Configure" << "-static" << openssl_config
|
129
|
+
cmd << "./Configure" << "threads" << "-static" << openssl_config
|
131
130
|
|
132
131
|
run( *cmd )
|
133
132
|
end
|
@@ -193,7 +192,7 @@ class CrossLibrary < OpenStruct
|
|
193
192
|
cmd << "CFLAGS=-L#{static_openssl_builddir}"
|
194
193
|
cmd << "LDFLAGS=-L#{static_openssl_builddir}"
|
195
194
|
cmd << "LDFLAGS_SL=-L#{static_openssl_builddir}"
|
196
|
-
cmd << "LIBS=-lwsock32 -lgdi32 -lws2_32 -lcrypt32"
|
195
|
+
cmd << "LIBS=-lssl -lwsock32 -lgdi32 -lws2_32 -lcrypt32"
|
197
196
|
cmd << "CPPFLAGS=-I#{static_openssl_builddir}/include"
|
198
197
|
|
199
198
|
run( *cmd )
|
@@ -207,6 +206,10 @@ class CrossLibrary < OpenStruct
|
|
207
206
|
chdir( static_postgresql_srcdir + "common" ) do
|
208
207
|
sh 'make', "-j#{NUM_CPUS}"
|
209
208
|
end
|
209
|
+
# Work around missing dependency to errorcodes.h in PostgreSQL-17.0
|
210
|
+
chdir( static_postgresql_srcdir + "backend" + "utils" ) do
|
211
|
+
sh 'make', "-j#{NUM_CPUS}"
|
212
|
+
end
|
210
213
|
chdir( static_postgresql_srcdir + "port" ) do
|
211
214
|
sh 'make', "-j#{NUM_CPUS}"
|
212
215
|
end
|
@@ -290,8 +293,9 @@ CrossLibraries.each do |xlib|
|
|
290
293
|
task "gem:windows:#{platform}" => ['gem:windows:prepare', xlib.openssl_tarball, xlib.postgresql_tarball] do
|
291
294
|
RakeCompilerDock.sh <<-EOT, platform: platform
|
292
295
|
(cp build/gem/gem-*.pem ~/.gem/ || true) &&
|
296
|
+
sudo apt-get update && sudo apt-get install -y bison flex &&
|
293
297
|
bundle install --local &&
|
294
|
-
rake native:#{platform} pkg/#{$gem_spec.full_name}-#{platform}.gem
|
298
|
+
rake native:#{platform} pkg/#{$gem_spec.full_name}-#{platform}.gem MAKEOPTS=-j`nproc` RUBY_CC_VERSION=3.3.0:3.2.0:3.1.0:3.0.0:2.7.0:2.6.0:2.5.0
|
295
299
|
EOT
|
296
300
|
end
|
297
301
|
desc "Build the windows binary gems"
|
data/ext/errorcodes.def
CHANGED
@@ -453,6 +453,10 @@
|
|
453
453
|
VALUE klass = define_error_class( "IdleInTransactionSessionTimeout", "25" );
|
454
454
|
register_error_class( "25P03", klass );
|
455
455
|
}
|
456
|
+
{
|
457
|
+
VALUE klass = define_error_class( "TransactionTimeout", "25" );
|
458
|
+
register_error_class( "25P04", klass );
|
459
|
+
}
|
456
460
|
{
|
457
461
|
VALUE klass = define_error_class( "InvalidSqlStatementName", NULL );
|
458
462
|
register_error_class( "26000", klass );
|
@@ -885,11 +889,6 @@
|
|
885
889
|
VALUE klass = define_error_class( "DuplicateFile", "58" );
|
886
890
|
register_error_class( "58P02", klass );
|
887
891
|
}
|
888
|
-
{
|
889
|
-
VALUE klass = define_error_class( "SnapshotTooOld", NULL );
|
890
|
-
register_error_class( "72000", klass );
|
891
|
-
register_error_class( "72", klass );
|
892
|
-
}
|
893
892
|
{
|
894
893
|
VALUE klass = define_error_class( "ConfigFileError", NULL );
|
895
894
|
register_error_class( "F0000", klass );
|
data/ext/errorcodes.txt
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# errcodes.txt
|
3
3
|
# PostgreSQL error codes
|
4
4
|
#
|
5
|
-
# Copyright (c) 2003-
|
5
|
+
# Copyright (c) 2003-2024, PostgreSQL Global Development Group
|
6
6
|
#
|
7
7
|
# This list serves as the basis for generating source files containing error
|
8
8
|
# codes. It is kept in a common format to make sure all these source files have
|
@@ -252,6 +252,7 @@ Section: Class 25 - Invalid Transaction State
|
|
252
252
|
25P01 E ERRCODE_NO_ACTIVE_SQL_TRANSACTION no_active_sql_transaction
|
253
253
|
25P02 E ERRCODE_IN_FAILED_SQL_TRANSACTION in_failed_sql_transaction
|
254
254
|
25P03 E ERRCODE_IDLE_IN_TRANSACTION_SESSION_TIMEOUT idle_in_transaction_session_timeout
|
255
|
+
25P04 E ERRCODE_TRANSACTION_TIMEOUT transaction_timeout
|
255
256
|
|
256
257
|
Section: Class 26 - Invalid SQL Statement Name
|
257
258
|
|
@@ -439,10 +440,6 @@ Section: Class 58 - System Error (errors external to PostgreSQL itself)
|
|
439
440
|
58P01 E ERRCODE_UNDEFINED_FILE undefined_file
|
440
441
|
58P02 E ERRCODE_DUPLICATE_FILE duplicate_file
|
441
442
|
|
442
|
-
Section: Class 72 - Snapshot Failure
|
443
|
-
# (class borrowed from Oracle)
|
444
|
-
72000 E ERRCODE_SNAPSHOT_TOO_OLD snapshot_too_old
|
445
|
-
|
446
443
|
Section: Class F0 - Configuration File Error
|
447
444
|
|
448
445
|
# (PostgreSQL-specific error class)
|
data/ext/extconf.rb
CHANGED
@@ -9,6 +9,8 @@ if ENV['MAINTAINER_MODE']
|
|
9
9
|
' -ggdb' <<
|
10
10
|
' -DDEBUG' <<
|
11
11
|
' -pedantic'
|
12
|
+
$LDFLAGS <<
|
13
|
+
' -ggdb'
|
12
14
|
end
|
13
15
|
|
14
16
|
if pgdir = with_config( 'pg' )
|
@@ -158,6 +160,7 @@ have_func 'timegm'
|
|
158
160
|
have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
|
159
161
|
have_func 'rb_gc_mark_movable' # since ruby-2.7
|
160
162
|
have_func 'rb_io_wait' # since ruby-3.0
|
163
|
+
have_func 'rb_io_descriptor' # since ruby-3.1
|
161
164
|
|
162
165
|
# unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
|
163
166
|
have_header 'unistd.h'
|
data/ext/pg.c
CHANGED
@@ -543,7 +543,7 @@ Init_pg_ext(void)
|
|
543
543
|
/* Result#result_error_field argument constant
|
544
544
|
*
|
545
545
|
* The SQLSTATE code for the error.
|
546
|
-
* The SQLSTATE code
|
546
|
+
* The SQLSTATE code identifies the type of error that has occurred; it can be used by front-end applications to perform specific operations (such as error handling) in response to a particular database error.
|
547
547
|
* For a list of the possible SQLSTATE codes, see Appendix A.
|
548
548
|
* This field is not localizable, and is always present.
|
549
549
|
*/
|
data/ext/pg_binary_decoder.c
CHANGED
@@ -233,6 +233,8 @@ j2date(int jd, int *year, int *month, int *day)
|
|
233
233
|
*
|
234
234
|
* This is a decoder class for conversion of PostgreSQL binary date
|
235
235
|
* to Ruby Date objects.
|
236
|
+
*
|
237
|
+
* As soon as this class is used, it requires the ruby standard library 'date'.
|
236
238
|
*/
|
237
239
|
static VALUE
|
238
240
|
pg_bin_dec_date(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
data/ext/pg_connection.c
CHANGED
@@ -33,8 +33,8 @@ static VALUE pgconn_async_flush(VALUE self);
|
|
33
33
|
#ifdef __GNUC__
|
34
34
|
__attribute__((format(printf, 3, 4)))
|
35
35
|
#endif
|
36
|
-
static void
|
37
|
-
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
36
|
+
NORETURN( static void
|
37
|
+
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...))
|
38
38
|
{
|
39
39
|
VALUE msg, error;
|
40
40
|
va_list ap;
|
@@ -264,6 +264,7 @@ pgconn_s_allocate( VALUE klass )
|
|
264
264
|
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
|
265
265
|
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
266
266
|
rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
|
267
|
+
rb_ivar_set(self, rb_intern("@iopts_for_reset"), Qnil);
|
267
268
|
|
268
269
|
return self;
|
269
270
|
}
|
@@ -515,9 +516,9 @@ static VALUE
|
|
515
516
|
pgconn_connect_poll(VALUE self)
|
516
517
|
{
|
517
518
|
PostgresPollingStatusType status;
|
518
|
-
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
519
519
|
|
520
520
|
pgconn_close_socket_io(self);
|
521
|
+
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
521
522
|
|
522
523
|
return INT2FIX((int)status);
|
523
524
|
}
|
@@ -615,9 +616,9 @@ static VALUE
|
|
615
616
|
pgconn_reset_poll(VALUE self)
|
616
617
|
{
|
617
618
|
PostgresPollingStatusType status;
|
618
|
-
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
619
619
|
|
620
620
|
pgconn_close_socket_io(self);
|
621
|
+
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
621
622
|
|
622
623
|
return INT2FIX((int)status);
|
623
624
|
}
|
@@ -2266,6 +2267,17 @@ pgconn_notifies(VALUE self)
|
|
2266
2267
|
return hash;
|
2267
2268
|
}
|
2268
2269
|
|
2270
|
+
#ifndef HAVE_RB_IO_DESCRIPTOR
|
2271
|
+
static int
|
2272
|
+
rb_io_descriptor(VALUE io)
|
2273
|
+
{
|
2274
|
+
Check_Type(io, T_FILE);
|
2275
|
+
rb_io_t *fptr = RFILE(io)->fptr;
|
2276
|
+
rb_io_check_closed(fptr);
|
2277
|
+
return fptr->fd;
|
2278
|
+
}
|
2279
|
+
#endif
|
2280
|
+
|
2269
2281
|
#if defined(_WIN32)
|
2270
2282
|
|
2271
2283
|
/* We use a specialized implementation of rb_io_wait() on Windows.
|
@@ -2286,7 +2298,6 @@ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
|
2286
2298
|
|
2287
2299
|
static VALUE
|
2288
2300
|
pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2289
|
-
rb_io_t *fptr;
|
2290
2301
|
struct timeval ptimeout;
|
2291
2302
|
|
2292
2303
|
struct timeval aborttime={0,0}, currtime, waittime;
|
@@ -2297,7 +2308,6 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2297
2308
|
long w32_events = 0;
|
2298
2309
|
DWORD wait_ret;
|
2299
2310
|
|
2300
|
-
GetOpenFile((io), fptr);
|
2301
2311
|
if( !NIL_P(timeout) ){
|
2302
2312
|
ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
|
2303
2313
|
ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
|
@@ -2311,7 +2321,7 @@ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2311
2321
|
if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
|
2312
2322
|
|
2313
2323
|
for(;;) {
|
2314
|
-
if ( WSAEventSelect(_get_osfhandle(
|
2324
|
+
if ( WSAEventSelect(_get_osfhandle(rb_io_descriptor(io)), hEvent, w32_events) == SOCKET_ERROR ) {
|
2315
2325
|
WSACloseEvent( hEvent );
|
2316
2326
|
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2317
2327
|
}
|
@@ -2354,7 +2364,7 @@ static VALUE
|
|
2354
2364
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2355
2365
|
#if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
|
2356
2366
|
/* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
|
2357
|
-
*
|
2367
|
+
* Fortunately ruby-3.1 offers a C-API for it.
|
2358
2368
|
*/
|
2359
2369
|
VALUE scheduler = rb_fiber_scheduler_current();
|
2360
2370
|
|
@@ -2384,16 +2394,14 @@ typedef enum {
|
|
2384
2394
|
|
2385
2395
|
static VALUE
|
2386
2396
|
pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
2387
|
-
rb_io_t *fptr;
|
2388
2397
|
struct timeval waittime;
|
2389
2398
|
int res;
|
2390
2399
|
|
2391
|
-
GetOpenFile((io), fptr);
|
2392
2400
|
if( !NIL_P(timeout) ){
|
2393
2401
|
waittime.tv_sec = (time_t)(NUM2DBL(timeout));
|
2394
2402
|
waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
|
2395
2403
|
}
|
2396
|
-
res = rb_wait_for_single_fd(
|
2404
|
+
res = rb_wait_for_single_fd(rb_io_descriptor(io), NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
|
2397
2405
|
|
2398
2406
|
return UINT2NUM(res);
|
2399
2407
|
}
|
@@ -3128,7 +3136,9 @@ pgconn_async_get_last_result(VALUE self)
|
|
3128
3136
|
for(;;) {
|
3129
3137
|
int status;
|
3130
3138
|
|
3131
|
-
/*
|
3139
|
+
/* Wait for input before reading each result.
|
3140
|
+
* That way we support the ruby-3.x IO scheduler and don't block other ruby threads.
|
3141
|
+
*/
|
3132
3142
|
wait_socket_readable(self, NULL, get_result_readable);
|
3133
3143
|
|
3134
3144
|
cur = gvl_PQgetResult(conn);
|
@@ -3162,7 +3172,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3162
3172
|
* Returns:
|
3163
3173
|
* * +nil+ when the connection is already idle
|
3164
3174
|
* * +true+ when some results have been discarded
|
3165
|
-
* * +false+ when a failure
|
3175
|
+
* * +false+ when a failure occurred and the connection was closed
|
3166
3176
|
*
|
3167
3177
|
*/
|
3168
3178
|
static VALUE
|
data/ext/pg_copy_coder.c
CHANGED
@@ -212,6 +212,7 @@ pg_copycoder_type_map_get(VALUE self)
|
|
212
212
|
*
|
213
213
|
* See also PG::TextDecoder::CopyRow for the decoding direction with
|
214
214
|
* PG::Connection#get_copy_data .
|
215
|
+
* And see PG::BinaryEncoder::CopyRow for an encoder of the COPY binary format.
|
215
216
|
*/
|
216
217
|
static int
|
217
218
|
pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
@@ -235,7 +236,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
235
236
|
char *ptr1;
|
236
237
|
char *ptr2;
|
237
238
|
int strlen;
|
238
|
-
int
|
239
|
+
int backslashes;
|
239
240
|
VALUE subint;
|
240
241
|
VALUE entry;
|
241
242
|
|
@@ -286,19 +287,19 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
286
287
|
ptr2 = current_out + strlen;
|
287
288
|
|
288
289
|
/* count required backlashs */
|
289
|
-
for(
|
290
|
+
for(backslashes = 0; ptr1 != ptr2; ptr1++) {
|
290
291
|
/* Escape backslash itself, newline, carriage return, and the current delimiter character. */
|
291
292
|
if(*ptr1 == '\\' || *ptr1 == '\n' || *ptr1 == '\r' || *ptr1 == this->delimiter){
|
292
|
-
|
293
|
+
backslashes++;
|
293
294
|
}
|
294
295
|
}
|
295
296
|
|
296
297
|
ptr1 = current_out + strlen;
|
297
|
-
ptr2 = current_out + strlen +
|
298
|
+
ptr2 = current_out + strlen + backslashes;
|
298
299
|
current_out = ptr2;
|
299
300
|
|
300
301
|
/* Then store the escaped string on the final position, walking
|
301
|
-
* right to left, until all
|
302
|
+
* right to left, until all backslashes are placed. */
|
302
303
|
while( ptr1 != ptr2 ) {
|
303
304
|
*--ptr2 = *--ptr1;
|
304
305
|
if(*ptr1 == '\\' || *ptr1 == '\n' || *ptr1 == '\r' || *ptr1 == this->delimiter){
|
@@ -358,6 +359,7 @@ pg_text_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedia
|
|
358
359
|
*
|
359
360
|
* See also PG::BinaryDecoder::CopyRow for the decoding direction with
|
360
361
|
* PG::Connection#get_copy_data .
|
362
|
+
* And see PG::TextEncoder::CopyRow for an encoder of the COPY text format.
|
361
363
|
*/
|
362
364
|
static int
|
363
365
|
pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
@@ -391,7 +393,7 @@ pg_bin_enc_copy_row(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediat
|
|
391
393
|
|
392
394
|
switch(TYPE(entry)){
|
393
395
|
case T_NIL:
|
394
|
-
/* 4 bytes for -1
|
396
|
+
/* 4 bytes for -1 indicating a NULL value */
|
395
397
|
PG_RB_STR_ENSURE_CAPA( *intermediate, 4, current_out, end_capa_ptr );
|
396
398
|
write_nbo32(-1, current_out);
|
397
399
|
current_out += 4;
|
@@ -496,6 +498,7 @@ GetDecimalFromHex(char hex)
|
|
496
498
|
*
|
497
499
|
* See also PG::TextEncoder::CopyRow for the encoding direction with
|
498
500
|
* PG::Connection#put_copy_data .
|
501
|
+
* And see PG::BinaryDecoder::CopyRow for a decoder of the COPY binary format.
|
499
502
|
*/
|
500
503
|
/*
|
501
504
|
* Parse the current line into separate attributes (fields),
|
@@ -763,6 +766,7 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
|
|
763
766
|
*
|
764
767
|
* See also PG::BinaryEncoder::CopyRow for the encoding direction with
|
765
768
|
* PG::Connection#put_copy_data .
|
769
|
+
* And see PG::TextDecoder::CopyRow for a decoder of the COPY text format.
|
766
770
|
*/
|
767
771
|
static VALUE
|
768
772
|
pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tuple, int _field, int enc_idx)
|
data/ext/pg_record_coder.c
CHANGED
@@ -198,7 +198,7 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
198
198
|
char *ptr1;
|
199
199
|
char *ptr2;
|
200
200
|
long strlen;
|
201
|
-
int
|
201
|
+
int backslashes;
|
202
202
|
VALUE subint;
|
203
203
|
VALUE entry;
|
204
204
|
|
@@ -249,19 +249,19 @@ pg_text_enc_record(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate
|
|
249
249
|
ptr2 = current_out + strlen;
|
250
250
|
|
251
251
|
/* count required backlashs */
|
252
|
-
for(
|
252
|
+
for(backslashes = 0; ptr1 != ptr2; ptr1++) {
|
253
253
|
/* Escape backslash itself, newline, carriage return, and the current delimiter character. */
|
254
254
|
if(*ptr1 == '"' || *ptr1 == '\\'){
|
255
|
-
|
255
|
+
backslashes++;
|
256
256
|
}
|
257
257
|
}
|
258
258
|
|
259
259
|
ptr1 = current_out + strlen;
|
260
|
-
ptr2 = current_out + strlen +
|
260
|
+
ptr2 = current_out + strlen + backslashes;
|
261
261
|
current_out = ptr2;
|
262
262
|
|
263
263
|
/* Then store the escaped string on the final position, walking
|
264
|
-
* right to left, until all
|
264
|
+
* right to left, until all backslashes are placed. */
|
265
265
|
while( ptr1 != ptr2 ) {
|
266
266
|
*--ptr2 = *--ptr1;
|
267
267
|
if(*ptr1 == '"' || *ptr1 == '\\'){
|
@@ -340,7 +340,7 @@ record_isspace(char ch)
|
|
340
340
|
* conn.exec("SELECT * FROM my_table").map_types!(PG::TypeMapByColumn.new([deco]*2)).to_a
|
341
341
|
* # => [{"v1"=>[2.0, 3.0], "v2"=>[4.0, 5.0]}, {"v1"=>[6.0, 7.0], "v2"=>[8.0, 9.0]}]
|
342
342
|
*
|
343
|
-
* It's more
|
343
|
+
* It's more convenient to use the PG::BasicTypeRegistry, which is based on database OIDs.
|
344
344
|
* # Fetch a NULL record of our type to retrieve the OIDs of the two fields "r" and "i"
|
345
345
|
* oids = conn.exec( "SELECT (NULL::complex).*" )
|
346
346
|
* # Build a type map (PG::TypeMapByColumn) for decoding the "complex" type
|
data/ext/pg_result.c
CHANGED
@@ -664,7 +664,7 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
664
664
|
* An example:
|
665
665
|
*
|
666
666
|
* begin
|
667
|
-
* conn.exec( "SELECT * FROM
|
667
|
+
* conn.exec( "SELECT * FROM nonexistent_table" )
|
668
668
|
* rescue PG::Error => err
|
669
669
|
* p [
|
670
670
|
* err.result.error_field( PG::Result::PG_DIAG_SEVERITY ),
|
@@ -684,7 +684,7 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
684
684
|
*
|
685
685
|
* Outputs:
|
686
686
|
*
|
687
|
-
* ["ERROR", "42P01", "relation \"
|
687
|
+
* ["ERROR", "42P01", "relation \"nonexistent_table\" does not exist", nil, nil,
|
688
688
|
* "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
|
689
689
|
*/
|
690
690
|
static VALUE
|
data/ext/pg_text_decoder.c
CHANGED
@@ -163,6 +163,8 @@ pg_text_dec_integer(t_pg_coder *conv, const char *val, int len, int tuple, int f
|
|
163
163
|
* This is a decoder class for conversion of PostgreSQL numeric types
|
164
164
|
* to Ruby BigDecimal objects.
|
165
165
|
*
|
166
|
+
* As soon as this class is used, it requires the 'bigdecimal' gem.
|
167
|
+
*
|
166
168
|
*/
|
167
169
|
static VALUE
|
168
170
|
pg_text_dec_numeric(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
@@ -174,7 +176,7 @@ pg_text_dec_numeric(t_pg_coder *conv, const char *val, int len, int tuple, int f
|
|
174
176
|
static VALUE
|
175
177
|
init_pg_text_decoder_numeric(VALUE rb_mPG_TextDecoder)
|
176
178
|
{
|
177
|
-
|
179
|
+
rb_funcall(rb_mPG, rb_intern("require_bigdecimal_without_warning"), 0);
|
178
180
|
s_id_BigDecimal = rb_intern("BigDecimal");
|
179
181
|
|
180
182
|
/* dummy = rb_define_class_under( rb_mPG_TextDecoder, "Numeric", rb_cPG_SimpleDecoder ); */
|
@@ -811,6 +813,7 @@ static VALUE pg_text_dec_timestamp(t_pg_coder *conv, const char *val, int len, i
|
|
811
813
|
* This is a decoder class for conversion of PostgreSQL inet type
|
812
814
|
* to Ruby IPAddr values.
|
813
815
|
*
|
816
|
+
* As soon as this class is used, it requires the ruby standard library 'ipaddr'.
|
814
817
|
*/
|
815
818
|
static VALUE
|
816
819
|
pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int field, int enc_idx)
|
data/ext/pg_text_encoder.c
CHANGED
@@ -119,6 +119,10 @@ pg_text_enc_boolean(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
119
119
|
int
|
120
120
|
pg_coder_enc_to_s(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
121
121
|
{
|
122
|
+
/* Attention:
|
123
|
+
* In contrast to all other encoders, the "this" pointer of this encoder can be NULL.
|
124
|
+
* This is because it is used as a fall-back if no encoder is defined.
|
125
|
+
*/
|
122
126
|
VALUE str = rb_obj_as_string(value);
|
123
127
|
if( ENCODING_GET(str) == enc_idx ){
|
124
128
|
*intermediate = str;
|
@@ -345,6 +349,8 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
345
349
|
*
|
346
350
|
* It converts Integer, Float and BigDecimal objects.
|
347
351
|
* All other objects are expected to respond to +to_s+.
|
352
|
+
*
|
353
|
+
* As soon as this class is used, it requires the 'bigdecimal' gem.
|
348
354
|
*/
|
349
355
|
static int
|
350
356
|
pg_text_enc_numeric(t_pg_coder *this, VALUE value, char *out, VALUE *intermediate, int enc_idx)
|
@@ -377,7 +383,7 @@ init_pg_text_encoder_numeric(VALUE rb_mPG_TextDecoder)
|
|
377
383
|
{
|
378
384
|
s_str_F = rb_str_freeze(rb_str_new_cstr("F"));
|
379
385
|
rb_global_variable(&s_str_F);
|
380
|
-
|
386
|
+
rb_funcall(rb_mPG, rb_intern("require_bigdecimal_without_warning"), 0);
|
381
387
|
s_cBigDecimal = rb_const_get(rb_cObject, rb_intern("BigDecimal"));
|
382
388
|
|
383
389
|
/* dummy = rb_define_class_under( rb_mPG_TextEncoder, "Numeric", rb_cPG_SimpleEncoder ); */
|
@@ -437,7 +443,7 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
437
443
|
t_pg_composite_coder *this = _this;
|
438
444
|
char *ptr1;
|
439
445
|
char *ptr2;
|
440
|
-
int
|
446
|
+
int backslashes = 0;
|
441
447
|
int needquote;
|
442
448
|
|
443
449
|
/* count data plus backslashes; detect chars needing quotes */
|
@@ -454,7 +460,7 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
454
460
|
|
455
461
|
if (ch == '"' || ch == '\\'){
|
456
462
|
needquote = 1;
|
457
|
-
|
463
|
+
backslashes++;
|
458
464
|
} else if (ch == '{' || ch == '}' || ch == this->delimiter ||
|
459
465
|
ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\v' || ch == '\f'){
|
460
466
|
needquote = 1;
|
@@ -463,12 +469,12 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
463
469
|
|
464
470
|
if( needquote ){
|
465
471
|
ptr1 = p_in + strlen;
|
466
|
-
ptr2 = p_out + strlen +
|
472
|
+
ptr2 = p_out + strlen + backslashes + 2;
|
467
473
|
/* Write end quote */
|
468
474
|
*--ptr2 = '"';
|
469
475
|
|
470
476
|
/* Then store the escaped string on the final position, walking
|
471
|
-
* right to left, until all
|
477
|
+
* right to left, until all backslashes are placed. */
|
472
478
|
while( ptr1 != p_in ) {
|
473
479
|
*--ptr2 = *--ptr1;
|
474
480
|
if(*ptr2 == '"' || *ptr2 == '\\'){
|
@@ -477,7 +483,7 @@ quote_array_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
477
483
|
}
|
478
484
|
/* Write start quote */
|
479
485
|
*p_out = '"';
|
480
|
-
return strlen +
|
486
|
+
return strlen + backslashes + 2;
|
481
487
|
} else {
|
482
488
|
if( p_in != p_out )
|
483
489
|
memcpy( p_out, p_in, strlen );
|
@@ -692,22 +698,22 @@ static int
|
|
692
698
|
quote_literal_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
693
699
|
char *ptr1;
|
694
700
|
char *ptr2;
|
695
|
-
int
|
701
|
+
int backslashes = 0;
|
696
702
|
|
697
703
|
/* count required backlashs */
|
698
704
|
for(ptr1 = p_in; ptr1 != p_in + strlen; ptr1++) {
|
699
705
|
if (*ptr1 == '\''){
|
700
|
-
|
706
|
+
backslashes++;
|
701
707
|
}
|
702
708
|
}
|
703
709
|
|
704
710
|
ptr1 = p_in + strlen;
|
705
|
-
ptr2 = p_out + strlen +
|
711
|
+
ptr2 = p_out + strlen + backslashes + 2;
|
706
712
|
/* Write end quote */
|
707
713
|
*--ptr2 = '\'';
|
708
714
|
|
709
715
|
/* Then store the escaped string on the final position, walking
|
710
|
-
* right to left, until all
|
716
|
+
* right to left, until all backslashes are placed. */
|
711
717
|
while( ptr1 != p_in ) {
|
712
718
|
*--ptr2 = *--ptr1;
|
713
719
|
if(*ptr2 == '\''){
|
@@ -716,7 +722,7 @@ quote_literal_buffer( void *_this, char *p_in, int strlen, char *p_out ){
|
|
716
722
|
}
|
717
723
|
/* Write start quote */
|
718
724
|
*p_out = '\'';
|
719
|
-
return strlen +
|
725
|
+
return strlen + backslashes + 2;
|
720
726
|
}
|
721
727
|
|
722
728
|
|