pg 1.2.3 → 1.3.1
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 +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +86 -0
- data/.github/workflows/source-gem.yml +130 -0
- data/.gitignore +13 -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.rdoc +95 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +7 -6
- data/Rakefile +27 -138
- data/Rakefile.cross +6 -5
- data/certs/ged.pem +24 -0
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.txt +3 -1
- data/ext/extconf.rb +91 -19
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +59 -4
- data/ext/pg.h +18 -1
- data/ext/pg_coder.c +82 -28
- data/ext/pg_connection.c +673 -493
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +39 -11
- data/ext/pg_result.c +61 -31
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -6
- data/ext/pg_tuple.c +47 -21
- data/ext/pg_type_map.c +41 -8
- data/ext/pg_type_map_all_strings.c +14 -1
- data/ext/pg_type_map_by_class.c +49 -24
- data/ext/pg_type_map_by_column.c +64 -28
- data/ext/pg_type_map_by_mri_type.c +47 -18
- data/ext/pg_type_map_by_oid.c +52 -23
- data/ext/pg_type_map_in_ruby.c +50 -19
- data/ext/pg_util.c +2 -2
- data/lib/pg/basic_type_map_based_on_result.rb +47 -0
- data/lib/pg/basic_type_map_for_queries.rb +193 -0
- data/lib/pg/basic_type_map_for_results.rb +81 -0
- data/lib/pg/basic_type_registry.rb +296 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +588 -58
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +47 -32
- 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 +32 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +106 -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.tar.gz.sig +0 -0
- metadata +76 -217
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- 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 -1123
- data/spec/pg_spec.rb +0 -50
data/ext/extconf.rb
CHANGED
@@ -15,6 +15,13 @@ if pgdir = with_config( 'pg' )
|
|
15
15
|
ENV['PATH'] = "#{pgdir}/bin" + File::PATH_SEPARATOR + ENV['PATH']
|
16
16
|
end
|
17
17
|
|
18
|
+
if enable_config("gvl-unlock", true)
|
19
|
+
$defs.push( "-DENABLE_GVL_UNLOCK" )
|
20
|
+
$stderr.puts "Calling libpq with GVL unlocked"
|
21
|
+
else
|
22
|
+
$stderr.puts "Calling libpq with GVL locked"
|
23
|
+
end
|
24
|
+
|
18
25
|
if enable_config("windows-cross")
|
19
26
|
# Avoid dependency to external libgcc.dll on x86-mingw32
|
20
27
|
$LDFLAGS << " -static-libgcc"
|
@@ -34,31 +41,93 @@ else
|
|
34
41
|
libdir = `"#{pgconfig}" --libdir`.chomp
|
35
42
|
dir_config 'pg', incdir, libdir
|
36
43
|
|
37
|
-
#
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
44
|
+
# Windows traditionally stores DLLs beside executables, not in libdir
|
45
|
+
dlldir = RUBY_PLATFORM=~/mingw|mswin/ ? `"#{pgconfig}" --bindir`.chomp : libdir
|
46
|
+
|
47
|
+
elsif checking_for "libpq per pkg-config" do
|
48
|
+
_cflags, ldflags, _libs = pkg_config("libpq")
|
49
|
+
dlldir = ldflags && ldflags[/-L([^ ]+)/] && $1
|
42
50
|
end
|
51
|
+
|
43
52
|
else
|
44
|
-
|
45
|
-
|
46
|
-
dir_config 'pg'
|
53
|
+
incdir, libdir = dir_config 'pg'
|
54
|
+
dlldir = libdir
|
47
55
|
end
|
56
|
+
|
57
|
+
# Try to use runtime path linker option, even if RbConfig doesn't know about it.
|
58
|
+
# The rpath option is usually set implicit by dir_config(), but so far not
|
59
|
+
# on MacOS-X.
|
60
|
+
if dlldir && RbConfig::CONFIG["RPATHFLAG"].to_s.empty?
|
61
|
+
append_ldflags "-Wl,-rpath,#{dlldir.quote}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
$stderr.puts "Using libpq from #{dlldir}"
|
66
|
+
|
67
|
+
File.write("postgresql_lib_path.rb", <<-EOT)
|
68
|
+
module PG
|
69
|
+
POSTGRESQL_LIB_PATH = #{dlldir.inspect}
|
48
70
|
end
|
71
|
+
EOT
|
72
|
+
$INSTALLFILES = {
|
73
|
+
"./postgresql_lib_path.rb" => "$(RUBYLIBDIR)/pg/"
|
74
|
+
}
|
49
75
|
|
50
76
|
if RUBY_VERSION >= '2.3.0' && /solaris/ =~ RUBY_PLATFORM
|
51
77
|
append_cppflags( '-D__EXTENSIONS__' )
|
52
78
|
end
|
53
79
|
|
54
|
-
|
55
|
-
find_header( 'libpq
|
56
|
-
find_header( '
|
80
|
+
begin
|
81
|
+
find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
|
82
|
+
find_header( 'libpq/libpq-fs.h' ) or abort "Can't find the 'libpq/libpq-fs.h header"
|
83
|
+
find_header( 'pg_config_manual.h' ) or abort "Can't find the 'pg_config_manual.h' header"
|
84
|
+
|
85
|
+
abort "Can't find the PostgreSQL client library (libpq)" unless
|
86
|
+
have_library( 'pq', 'PQconnectdb', ['libpq-fe.h'] ) ||
|
87
|
+
have_library( 'libpq', 'PQconnectdb', ['libpq-fe.h'] ) ||
|
88
|
+
have_library( 'ms/libpq', 'PQconnectdb', ['libpq-fe.h'] )
|
89
|
+
|
90
|
+
rescue SystemExit => err
|
91
|
+
install_text = case RUBY_PLATFORM
|
92
|
+
when /linux/
|
93
|
+
<<-EOT
|
94
|
+
Please install libpq or postgresql client package like so:
|
95
|
+
sudo apt install libpq-dev
|
96
|
+
sudo yum install postgresql-devel
|
97
|
+
sudo zypper in postgresql-devel
|
98
|
+
sudo pacman -S postgresql-libs
|
99
|
+
EOT
|
100
|
+
when /darwin/
|
101
|
+
<<-EOT
|
102
|
+
Please install libpq or postgresql client package like so:
|
103
|
+
brew install libpq
|
104
|
+
EOT
|
105
|
+
when /mingw/
|
106
|
+
<<-EOT
|
107
|
+
Please install libpq or postgresql client package like so:
|
108
|
+
ridk exec sh -c "pacman -S ${MINGW_PACKAGE_PREFIX}-postgresql"
|
109
|
+
EOT
|
110
|
+
else
|
111
|
+
<<-EOT
|
112
|
+
Please install libpq or postgresql client package.
|
113
|
+
EOT
|
114
|
+
end
|
115
|
+
|
116
|
+
$stderr.puts <<-EOT
|
117
|
+
*****************************************************************************
|
118
|
+
|
119
|
+
Unable to find PostgreSQL client library.
|
120
|
+
|
121
|
+
#{install_text}
|
122
|
+
or try again with:
|
123
|
+
gem install pg -- --with-pg-config=/path/to/pg_config
|
57
124
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
125
|
+
or set library paths manually with:
|
126
|
+
gem install pg -- --with-pg-include=/path/to/libpq-fe.h/ --with-pg-lib=/path/to/libpq.so/
|
127
|
+
|
128
|
+
EOT
|
129
|
+
raise
|
130
|
+
end
|
62
131
|
|
63
132
|
if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
|
64
133
|
# Work around: https://sourceware.org/bugzilla/show_bug.cgi?id=22504
|
@@ -69,21 +138,24 @@ if /mingw/ =~ RUBY_PLATFORM && RbConfig::MAKEFILE_CONFIG['CC'] =~ /gcc/
|
|
69
138
|
end
|
70
139
|
end
|
71
140
|
|
72
|
-
|
73
|
-
have_func 'PQsetSingleRowMode' or
|
141
|
+
have_func 'PQconninfo' or
|
74
142
|
abort "Your PostgreSQL is too old. Either install an older version " +
|
75
|
-
"of this gem or upgrade your database to at least PostgreSQL-9.
|
76
|
-
|
143
|
+
"of this gem or upgrade your database to at least PostgreSQL-9.3."
|
144
|
+
# optional headers/functions
|
77
145
|
have_func 'PQsslAttribute' # since PostgreSQL-9.5
|
78
146
|
have_func 'PQresultVerboseErrorMessage' # since PostgreSQL-9.6
|
79
147
|
have_func 'PQencryptPasswordConn' # since PostgreSQL-10
|
80
148
|
have_func 'PQresultMemorySize' # since PostgreSQL-12
|
149
|
+
have_func 'PQenterPipelineMode' # since PostgreSQL-14
|
81
150
|
have_func 'timegm'
|
82
151
|
have_func 'rb_gc_adjust_memory_usage' # since ruby-2.4
|
152
|
+
have_func 'rb_gc_mark_movable' # since ruby-2.7
|
153
|
+
have_func 'rb_io_wait' # since ruby-3.0
|
83
154
|
|
84
155
|
# unistd.h confilicts with ruby/win32.h when cross compiling for win32 and ruby 1.9.1
|
85
156
|
have_header 'unistd.h'
|
86
157
|
have_header 'inttypes.h'
|
158
|
+
have_header('ruby/fiber/scheduler.h') if RUBY_PLATFORM=~/mingw|mswin/
|
87
159
|
|
88
160
|
checking_for "C99 variable length arrays" do
|
89
161
|
$defs.push( "-DHAVE_VARIABLE_LENGTH_ARRAYS" ) if try_compile('void test_vla(int l){ int vla[l]; }')
|
data/ext/gvl_wrappers.c
CHANGED
@@ -9,9 +9,13 @@
|
|
9
9
|
char *PQencryptPasswordConn(PGconn *conn, const char *passwd, const char *user, const char *algorithm){return NULL;}
|
10
10
|
#endif
|
11
11
|
|
12
|
+
#ifdef ENABLE_GVL_UNLOCK
|
12
13
|
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
|
13
14
|
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_SKELETON );
|
15
|
+
#endif
|
14
16
|
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
|
17
|
+
#ifdef ENABLE_GVL_UNLOCK
|
15
18
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
|
16
19
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
|
20
|
+
#endif
|
17
21
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
|
data/ext/gvl_wrappers.h
CHANGED
@@ -17,6 +17,10 @@
|
|
17
17
|
|
18
18
|
#include <ruby/thread.h>
|
19
19
|
|
20
|
+
#ifdef RUBY_EXTCONF_H
|
21
|
+
# include RUBY_EXTCONF_H
|
22
|
+
#endif
|
23
|
+
|
20
24
|
#define DEFINE_PARAM_LIST1(type, name) \
|
21
25
|
name,
|
22
26
|
|
@@ -46,6 +50,7 @@
|
|
46
50
|
return NULL; \
|
47
51
|
}
|
48
52
|
|
53
|
+
#ifdef ENABLE_GVL_UNLOCK
|
49
54
|
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
50
55
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
51
56
|
struct gvl_wrapper_##name##_params params = { \
|
@@ -54,6 +59,13 @@
|
|
54
59
|
rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms, RUBY_UBF_IO, 0); \
|
55
60
|
when_non_void( return params.retval; ) \
|
56
61
|
}
|
62
|
+
#else
|
63
|
+
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
64
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
65
|
+
when_non_void( return ) \
|
66
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
67
|
+
}
|
68
|
+
#endif
|
57
69
|
|
58
70
|
#define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
59
71
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
|
@@ -66,6 +78,7 @@
|
|
66
78
|
return NULL; \
|
67
79
|
}
|
68
80
|
|
81
|
+
#ifdef ENABLE_GVL_UNLOCK
|
69
82
|
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
70
83
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
71
84
|
struct gvl_wrapper_##name##_params params = { \
|
@@ -74,6 +87,13 @@
|
|
74
87
|
rb_thread_call_with_gvl(gvl_##name##_skeleton, ¶ms); \
|
75
88
|
when_non_void( return params.retval; ) \
|
76
89
|
}
|
90
|
+
#else
|
91
|
+
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
92
|
+
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
93
|
+
when_non_void( return ) \
|
94
|
+
name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
95
|
+
}
|
96
|
+
#endif
|
77
97
|
|
78
98
|
#define GVL_TYPE_VOID(string)
|
79
99
|
#define GVL_TYPE_NONVOID(string) string
|
@@ -95,6 +115,8 @@
|
|
95
115
|
|
96
116
|
#define FOR_EACH_PARAM_OF_PQresetPoll(param)
|
97
117
|
|
118
|
+
#define FOR_EACH_PARAM_OF_PQping(param)
|
119
|
+
|
98
120
|
#define FOR_EACH_PARAM_OF_PQexec(param) \
|
99
121
|
param(PGconn *, conn)
|
100
122
|
|
@@ -196,6 +218,7 @@
|
|
196
218
|
function(PQreset, GVL_TYPE_VOID, void, PGconn *, conn) \
|
197
219
|
function(PQresetStart, GVL_TYPE_NONVOID, int, PGconn *, conn) \
|
198
220
|
function(PQresetPoll, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
|
221
|
+
function(PQping, GVL_TYPE_NONVOID, PGPing, const char *, conninfo) \
|
199
222
|
function(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
|
200
223
|
function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
201
224
|
function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
data/ext/pg.c
CHANGED
@@ -47,6 +47,7 @@
|
|
47
47
|
*/
|
48
48
|
|
49
49
|
#include "pg.h"
|
50
|
+
#include "pg_config.h"
|
50
51
|
|
51
52
|
int pg_skip_deprecation_warning;
|
52
53
|
VALUE rb_mPG;
|
@@ -415,14 +416,34 @@ Init_pg_ext()
|
|
415
416
|
rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
|
416
417
|
/* Waiting for a response from the server. */
|
417
418
|
rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
|
418
|
-
/* Received authentication; waiting for backend
|
419
|
+
/* Received authentication; waiting for backend startup. */
|
419
420
|
rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
|
421
|
+
/* This state is no longer used. */
|
422
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
420
423
|
/* Negotiating SSL encryption. */
|
421
424
|
rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
|
422
|
-
/* Negotiating environment-driven parameter settings. */
|
423
|
-
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
424
425
|
/* Internal state - PG.connect() needed. */
|
425
426
|
rb_define_const(rb_mPGconstants, "CONNECTION_NEEDED", INT2FIX(CONNECTION_NEEDED));
|
427
|
+
#if PG_MAJORVERSION_NUM >= 10
|
428
|
+
/* Checking if session is read-write. Available since PostgreSQL-10. */
|
429
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_WRITABLE", INT2FIX(CONNECTION_CHECK_WRITABLE));
|
430
|
+
#endif
|
431
|
+
#if PG_MAJORVERSION_NUM >= 10
|
432
|
+
/* Consuming any extra messages. Available since PostgreSQL-10. */
|
433
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CONSUME", INT2FIX(CONNECTION_CONSUME));
|
434
|
+
#endif
|
435
|
+
#if PG_MAJORVERSION_NUM >= 12
|
436
|
+
/* Negotiating GSSAPI. Available since PostgreSQL-12. */
|
437
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_GSS_STARTUP", INT2FIX(CONNECTION_GSS_STARTUP));
|
438
|
+
#endif
|
439
|
+
#if PG_MAJORVERSION_NUM >= 13
|
440
|
+
/* Checking target server properties. Available since PostgreSQL-13. */
|
441
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_TARGET", INT2FIX(CONNECTION_CHECK_TARGET));
|
442
|
+
#endif
|
443
|
+
#if PG_MAJORVERSION_NUM >= 14
|
444
|
+
/* Checking if server is in standby mode. Available since PostgreSQL-14. */
|
445
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_CHECK_STANDBY", INT2FIX(CONNECTION_CHECK_STANDBY));
|
446
|
+
#endif
|
426
447
|
|
427
448
|
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
|
428
449
|
|
@@ -526,6 +547,19 @@ Init_pg_ext()
|
|
526
547
|
/* Result#result_status constant - Single tuple from larger resultset. */
|
527
548
|
rb_define_const(rb_mPGconstants, "PGRES_SINGLE_TUPLE", INT2FIX(PGRES_SINGLE_TUPLE));
|
528
549
|
|
550
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
551
|
+
/* Result#result_status constant - The PG::Result represents a synchronization point in pipeline mode, requested by Connection#pipeline_sync.
|
552
|
+
*
|
553
|
+
* This status occurs only when pipeline mode has been selected. */
|
554
|
+
rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_SYNC", INT2FIX(PGRES_PIPELINE_SYNC));
|
555
|
+
|
556
|
+
/* Result#result_status constant - The PG::Result represents a pipeline that has received an error from the server.
|
557
|
+
*
|
558
|
+
* Connection#get_result must be called repeatedly, and each time it will return this status code until the end of the current pipeline, at which point it will return PG::PGRES_PIPELINE_SYNC and normal processing can resume.
|
559
|
+
*/
|
560
|
+
rb_define_const(rb_mPGconstants, "PGRES_PIPELINE_ABORTED", INT2FIX(PGRES_PIPELINE_ABORTED));
|
561
|
+
#endif
|
562
|
+
|
529
563
|
/****** Result CONSTANTS: result error field codes ******/
|
530
564
|
|
531
565
|
/* Result#result_error_field argument constant
|
@@ -549,7 +583,7 @@ Init_pg_ext()
|
|
549
583
|
/* Result#result_error_field argument constant
|
550
584
|
*
|
551
585
|
* The SQLSTATE code for the error.
|
552
|
-
* The SQLSTATE code identies the type of error that has occurred; it can be used by front-end applications to perform
|
586
|
+
* The SQLSTATE code identies 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.
|
553
587
|
* For a list of the possible SQLSTATE codes, see Appendix A.
|
554
588
|
* This field is not localizable, and is always present.
|
555
589
|
*/
|
@@ -645,6 +679,27 @@ Init_pg_ext()
|
|
645
679
|
rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
|
646
680
|
#endif
|
647
681
|
|
682
|
+
#ifdef HAVE_PQENTERPIPELINEMODE
|
683
|
+
/* Connection#pipeline_status constant
|
684
|
+
*
|
685
|
+
* The libpq connection is in pipeline mode.
|
686
|
+
*/
|
687
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ON", INT2FIX(PQ_PIPELINE_ON));
|
688
|
+
|
689
|
+
/* Connection#pipeline_status constant
|
690
|
+
*
|
691
|
+
* The libpq connection is not in pipeline mode.
|
692
|
+
*/
|
693
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_OFF", INT2FIX(PQ_PIPELINE_OFF));
|
694
|
+
|
695
|
+
/* Connection#pipeline_status constant
|
696
|
+
*
|
697
|
+
* The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
|
698
|
+
* The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
|
699
|
+
*/
|
700
|
+
rb_define_const(rb_mPGconstants, "PQ_PIPELINE_ABORTED", INT2FIX(PQ_PIPELINE_ABORTED));
|
701
|
+
#endif
|
702
|
+
|
648
703
|
/* Invalid OID constant */
|
649
704
|
rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
|
650
705
|
rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
|
data/ext/pg.h
CHANGED
@@ -11,6 +11,7 @@
|
|
11
11
|
#include <sys/types.h>
|
12
12
|
#if !defined(_WIN32)
|
13
13
|
# include <sys/time.h>
|
14
|
+
# include <sys/socket.h>
|
14
15
|
#endif
|
15
16
|
#if defined(HAVE_UNISTD_H) && !defined(_WIN32)
|
16
17
|
# include <unistd.h>
|
@@ -78,6 +79,15 @@ typedef long suseconds_t;
|
|
78
79
|
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
79
80
|
#endif
|
80
81
|
|
82
|
+
#ifdef HAVE_RB_GC_MARK_MOVABLE
|
83
|
+
#define pg_compact_callback(x) (x)
|
84
|
+
#define pg_gc_location(x) x = rb_gc_location(x)
|
85
|
+
#else
|
86
|
+
#define rb_gc_mark_movable(x) rb_gc_mark(x)
|
87
|
+
#define pg_compact_callback(x) {(x)}
|
88
|
+
#define pg_gc_location(x) UNUSED(x)
|
89
|
+
#endif
|
90
|
+
|
81
91
|
#define PG_ENC_IDX_BITS 28
|
82
92
|
|
83
93
|
/* The data behind each PG::Connection object */
|
@@ -104,6 +114,8 @@ typedef struct {
|
|
104
114
|
int enc_idx : PG_ENC_IDX_BITS;
|
105
115
|
/* flags controlling Symbol/String field names */
|
106
116
|
unsigned int flags : 2;
|
117
|
+
/* enable automatic flushing of send data at the end of send_query calls */
|
118
|
+
unsigned int flush_data : 1;
|
107
119
|
|
108
120
|
#if defined(_WIN32)
|
109
121
|
/* File descriptor to be used for rb_w32_unwrap_io_handle() */
|
@@ -220,6 +232,8 @@ typedef struct {
|
|
220
232
|
} convs[0];
|
221
233
|
} t_tmbc;
|
222
234
|
|
235
|
+
extern const rb_data_type_t pg_typemap_type;
|
236
|
+
extern const rb_data_type_t pg_coder_type;
|
223
237
|
|
224
238
|
#include "gvl_wrappers.h"
|
225
239
|
|
@@ -304,7 +318,7 @@ VALUE pg_obj_to_i _(( VALUE ));
|
|
304
318
|
VALUE pg_tmbc_allocate _(( void ));
|
305
319
|
void pg_coder_init_encoder _(( VALUE ));
|
306
320
|
void pg_coder_init_decoder _(( VALUE ));
|
307
|
-
void
|
321
|
+
void pg_coder_compact _(( void * ));
|
308
322
|
char *pg_rb_str_ensure_capa _(( VALUE, long, char *, char ** ));
|
309
323
|
|
310
324
|
#define PG_RB_STR_ENSURE_CAPA( str, expand_len, curr_ptr, end_ptr ) \
|
@@ -324,6 +338,9 @@ int pg_typemap_fit_to_copy_get _(( VALUE ));
|
|
324
338
|
VALUE pg_typemap_result_value _(( t_typemap *, VALUE, int, int ));
|
325
339
|
t_pg_coder *pg_typemap_typecast_query_param _(( t_typemap *, VALUE, int ));
|
326
340
|
VALUE pg_typemap_typecast_copy_get _(( t_typemap *, VALUE, int, int, int ));
|
341
|
+
void pg_typemap_mark _(( void * ));
|
342
|
+
size_t pg_typemap_memsize _(( const void * ));
|
343
|
+
void pg_typemap_compact _(( void * ));
|
327
344
|
|
328
345
|
PGconn *pg_get_pgconn _(( VALUE ));
|
329
346
|
t_pg_connection *pg_get_connection _(( VALUE ));
|
data/ext/pg_coder.c
CHANGED
@@ -26,11 +26,11 @@ 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
|
}
|
@@ -45,12 +45,12 @@ 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
|
}
|
@@ -61,32 +61,74 @@ pg_coder_init_decoder( VALUE self )
|
|
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
|
+
|
64
78
|
void
|
65
|
-
|
79
|
+
pg_coder_compact(void *_this)
|
66
80
|
{
|
67
|
-
|
81
|
+
t_pg_coder *this = (t_pg_coder *)_this;
|
82
|
+
pg_gc_location(this->coder_obj);
|
68
83
|
}
|
69
84
|
|
70
85
|
static void
|
71
|
-
|
86
|
+
pg_composite_coder_compact(void *_this)
|
72
87
|
{
|
73
|
-
|
88
|
+
t_pg_composite_coder *this = (t_pg_composite_coder *)_this;
|
89
|
+
pg_coder_compact(&this->comp);
|
74
90
|
}
|
75
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
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
103
|
+
};
|
104
|
+
|
76
105
|
static VALUE
|
77
106
|
pg_simple_encoder_allocate( VALUE klass )
|
78
107
|
{
|
79
108
|
t_pg_coder *this;
|
80
|
-
VALUE self =
|
109
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
81
110
|
pg_coder_init_encoder( self );
|
82
111
|
return self;
|
83
112
|
}
|
84
113
|
|
114
|
+
static const rb_data_type_t pg_composite_coder_type = {
|
115
|
+
"PG::CompositeCoder",
|
116
|
+
{
|
117
|
+
(RUBY_DATA_FUNC) NULL,
|
118
|
+
RUBY_TYPED_DEFAULT_FREE,
|
119
|
+
pg_composite_coder_memsize,
|
120
|
+
pg_compact_callback(pg_composite_coder_compact),
|
121
|
+
},
|
122
|
+
&pg_coder_type,
|
123
|
+
0,
|
124
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
125
|
+
};
|
126
|
+
|
85
127
|
static VALUE
|
86
128
|
pg_composite_encoder_allocate( VALUE klass )
|
87
129
|
{
|
88
130
|
t_pg_composite_coder *this;
|
89
|
-
VALUE self =
|
131
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
90
132
|
pg_coder_init_encoder( self );
|
91
133
|
this->elem = NULL;
|
92
134
|
this->needs_quotation = 1;
|
@@ -99,7 +141,7 @@ static VALUE
|
|
99
141
|
pg_simple_decoder_allocate( VALUE klass )
|
100
142
|
{
|
101
143
|
t_pg_coder *this;
|
102
|
-
VALUE self =
|
144
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_coder, &pg_coder_type, this );
|
103
145
|
pg_coder_init_decoder( self );
|
104
146
|
return self;
|
105
147
|
}
|
@@ -108,7 +150,7 @@ static VALUE
|
|
108
150
|
pg_composite_decoder_allocate( VALUE klass )
|
109
151
|
{
|
110
152
|
t_pg_composite_coder *this;
|
111
|
-
VALUE self =
|
153
|
+
VALUE self = TypedData_Make_Struct( klass, t_pg_composite_coder, &pg_composite_coder_type, this );
|
112
154
|
pg_coder_init_decoder( self );
|
113
155
|
this->elem = NULL;
|
114
156
|
this->needs_quotation = 1;
|
@@ -135,7 +177,7 @@ pg_coder_encode(int argc, VALUE *argv, VALUE self)
|
|
135
177
|
VALUE value;
|
136
178
|
int len, len2;
|
137
179
|
int enc_idx;
|
138
|
-
t_pg_coder *this =
|
180
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
139
181
|
|
140
182
|
if(argc < 1 || argc > 2){
|
141
183
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..2)", argc);
|
@@ -192,7 +234,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
192
234
|
int tuple = -1;
|
193
235
|
int field = -1;
|
194
236
|
VALUE res;
|
195
|
-
t_pg_coder *this =
|
237
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
196
238
|
|
197
239
|
if(argc < 1 || argc > 3){
|
198
240
|
rb_raise(rb_eArgError, "wrong number of arguments (%i for 1..3)", argc);
|
@@ -213,7 +255,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
213
255
|
rb_raise(rb_eRuntimeError, "no decoder function defined");
|
214
256
|
}
|
215
257
|
|
216
|
-
res = this->dec_func(this, val,
|
258
|
+
res = this->dec_func(this, val, RSTRING_LENINT(argv[0]), tuple, field, ENCODING_GET(argv[0]));
|
217
259
|
|
218
260
|
return res;
|
219
261
|
}
|
@@ -230,7 +272,7 @@ pg_coder_decode(int argc, VALUE *argv, VALUE self)
|
|
230
272
|
static VALUE
|
231
273
|
pg_coder_oid_set(VALUE self, VALUE oid)
|
232
274
|
{
|
233
|
-
t_pg_coder *this =
|
275
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
234
276
|
this->oid = NUM2UINT(oid);
|
235
277
|
return oid;
|
236
278
|
}
|
@@ -245,7 +287,7 @@ pg_coder_oid_set(VALUE self, VALUE oid)
|
|
245
287
|
static VALUE
|
246
288
|
pg_coder_oid_get(VALUE self)
|
247
289
|
{
|
248
|
-
t_pg_coder *this =
|
290
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
249
291
|
return UINT2NUM(this->oid);
|
250
292
|
}
|
251
293
|
|
@@ -261,7 +303,7 @@ pg_coder_oid_get(VALUE self)
|
|
261
303
|
static VALUE
|
262
304
|
pg_coder_format_set(VALUE self, VALUE format)
|
263
305
|
{
|
264
|
-
t_pg_coder *this =
|
306
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
265
307
|
this->format = NUM2INT(format);
|
266
308
|
return format;
|
267
309
|
}
|
@@ -276,7 +318,7 @@ pg_coder_format_set(VALUE self, VALUE format)
|
|
276
318
|
static VALUE
|
277
319
|
pg_coder_format_get(VALUE self)
|
278
320
|
{
|
279
|
-
t_pg_coder *this =
|
321
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
280
322
|
return INT2NUM(this->format);
|
281
323
|
}
|
282
324
|
|
@@ -292,7 +334,7 @@ pg_coder_format_get(VALUE self)
|
|
292
334
|
static VALUE
|
293
335
|
pg_coder_flags_set(VALUE self, VALUE flags)
|
294
336
|
{
|
295
|
-
t_pg_coder *this =
|
337
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
296
338
|
this->flags = NUM2INT(flags);
|
297
339
|
return flags;
|
298
340
|
}
|
@@ -306,7 +348,7 @@ pg_coder_flags_set(VALUE self, VALUE flags)
|
|
306
348
|
static VALUE
|
307
349
|
pg_coder_flags_get(VALUE self)
|
308
350
|
{
|
309
|
-
t_pg_coder *this =
|
351
|
+
t_pg_coder *this = RTYPEDDATA_DATA(self);
|
310
352
|
return INT2NUM(this->flags);
|
311
353
|
}
|
312
354
|
|
@@ -323,7 +365,7 @@ pg_coder_flags_get(VALUE self)
|
|
323
365
|
static VALUE
|
324
366
|
pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
325
367
|
{
|
326
|
-
t_pg_composite_coder *this =
|
368
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
327
369
|
this->needs_quotation = RTEST(needs_quotation);
|
328
370
|
return needs_quotation;
|
329
371
|
}
|
@@ -338,7 +380,7 @@ pg_coder_needs_quotation_set(VALUE self, VALUE needs_quotation)
|
|
338
380
|
static VALUE
|
339
381
|
pg_coder_needs_quotation_get(VALUE self)
|
340
382
|
{
|
341
|
-
t_pg_composite_coder *this =
|
383
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
342
384
|
return this->needs_quotation ? Qtrue : Qfalse;
|
343
385
|
}
|
344
386
|
|
@@ -353,7 +395,7 @@ pg_coder_needs_quotation_get(VALUE self)
|
|
353
395
|
static VALUE
|
354
396
|
pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
355
397
|
{
|
356
|
-
t_pg_composite_coder *this =
|
398
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
357
399
|
StringValue(delimiter);
|
358
400
|
if(RSTRING_LEN(delimiter) != 1)
|
359
401
|
rb_raise( rb_eArgError, "delimiter size must be one byte");
|
@@ -370,7 +412,7 @@ pg_coder_delimiter_set(VALUE self, VALUE delimiter)
|
|
370
412
|
static VALUE
|
371
413
|
pg_coder_delimiter_get(VALUE self)
|
372
414
|
{
|
373
|
-
t_pg_composite_coder *this =
|
415
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA(self);
|
374
416
|
return rb_str_new(&this->delimiter, 1);
|
375
417
|
}
|
376
418
|
|
@@ -386,12 +428,12 @@ pg_coder_delimiter_get(VALUE self)
|
|
386
428
|
static VALUE
|
387
429
|
pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
388
430
|
{
|
389
|
-
t_pg_composite_coder *this =
|
431
|
+
t_pg_composite_coder *this = RTYPEDDATA_DATA( self );
|
390
432
|
|
391
433
|
if ( NIL_P(elem_type) ){
|
392
434
|
this->elem = NULL;
|
393
435
|
} else if ( rb_obj_is_kind_of(elem_type, rb_cPG_Coder) ){
|
394
|
-
this->elem =
|
436
|
+
this->elem = RTYPEDDATA_DATA( elem_type );
|
395
437
|
} else {
|
396
438
|
rb_raise( rb_eTypeError, "wrong elements type %s (expected some kind of PG::Coder)",
|
397
439
|
rb_obj_classname( elem_type ) );
|
@@ -401,10 +443,22 @@ pg_coder_elements_type_set(VALUE self, VALUE elem_type)
|
|
401
443
|
return elem_type;
|
402
444
|
}
|
403
445
|
|
446
|
+
static const rb_data_type_t pg_coder_cfunc_type = {
|
447
|
+
"PG::Coder::CFUNC",
|
448
|
+
{
|
449
|
+
(RUBY_DATA_FUNC)NULL,
|
450
|
+
(RUBY_DATA_FUNC)NULL,
|
451
|
+
(size_t (*)(const void *))NULL,
|
452
|
+
},
|
453
|
+
0,
|
454
|
+
0,
|
455
|
+
RUBY_TYPED_FREE_IMMEDIATELY,
|
456
|
+
};
|
457
|
+
|
404
458
|
void
|
405
459
|
pg_define_coder( const char *name, void *func, VALUE base_klass, VALUE nsp )
|
406
460
|
{
|
407
|
-
VALUE cfunc_obj =
|
461
|
+
VALUE cfunc_obj = TypedData_Wrap_Struct( rb_cObject, &pg_coder_cfunc_type, func );
|
408
462
|
VALUE coder_klass = rb_define_class_under( nsp, name, base_klass );
|
409
463
|
if( nsp==rb_mPG_BinaryEncoder || nsp==rb_mPG_BinaryDecoder )
|
410
464
|
rb_include_module( coder_klass, rb_mPG_BinaryFormatting );
|