pg 0.16.0-x64-mingw32 → 0.17.0-x64-mingw32
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.tar.gz.sig +0 -0
- data/ChangeLog +122 -1
- data/History.rdoc +15 -0
- data/Rakefile +6 -2
- data/Rakefile.cross +1 -1
- data/ext/gvl_wrappers.h +45 -3
- data/ext/pg_connection.c +13 -8
- data/ext/pg_result.c +2 -2
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/pg.rb +3 -1
- data/lib/pg/connection.rb +85 -0
- data/spec/lib/helpers.rb +6 -0
- data/spec/pg/connection_spec.rb +95 -0
- metadata +19 -7
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
|
4
|
-
|
3
|
+
metadata.gz: 21f53fb93db689d13bbec315cbf5190e22581120
|
4
|
+
data.tar.gz: 59fe2cf2c7bedfe9d1295779e434e52812a0cb26
|
5
5
|
SHA512:
|
6
|
-
|
7
|
-
|
6
|
+
metadata.gz: 79f561112dee71eec9cfeb84f94a253f1ac2c9cdfc1e5227a7c96ea1e07a37940a6c35be804d425ebe282cd7a3cf8e2ddfd9fff20ccf67aa5ec099fd2afd1634
|
7
|
+
data.tar.gz: 26ec759a2af8b649ea4a11b3521a99536f2af838da7e94ea77b7c2a4916bcbd209876b58fc50fa3990e7f15fd9e060a8706e7bdcddd4191d6e5168df6765cf32
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/ChangeLog
CHANGED
@@ -1,8 +1,129 @@
|
|
1
|
+
2013-09-16 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* .hgtags:
|
4
|
+
Added tag v0.17.0 for changeset 30da9c169efc
|
5
|
+
[46f35f5b396e] [tip]
|
6
|
+
|
7
|
+
* .hgsigs:
|
8
|
+
Added signature for changeset eed93df350a6
|
9
|
+
[30da9c169efc] [v0.17.0]
|
10
|
+
|
11
|
+
* .hoerc:
|
12
|
+
Add the Gemfile to the list of files that don't have to be on the
|
13
|
+
Manifest.
|
14
|
+
[eed93df350a6]
|
15
|
+
|
16
|
+
2013-09-15 Michael Granger <ged@FaerieMUD.org>
|
17
|
+
|
18
|
+
* History.rdoc, lib/pg.rb:
|
19
|
+
Bump minor version
|
20
|
+
[7cdff0a462e5]
|
21
|
+
|
22
|
+
2013-09-14 Lars Kanis <lars@greiz-reinsdorf.de>
|
23
|
+
|
24
|
+
* History.rdoc:
|
25
|
+
Add change of PG::Result#check to History.rdoc.
|
26
|
+
[2b4f876c54f6]
|
27
|
+
|
28
|
+
* spec/lib/helpers.rb:
|
29
|
+
verify_clean_exec_status itself should leave a clean status.
|
30
|
+
[933d0f788047]
|
31
|
+
|
32
|
+
2013-09-13 Lars Kanis <lars@greiz-reinsdorf.de>
|
33
|
+
|
34
|
+
* lib/pg.rb, lib/pg/connection.rb, spec/lib/helpers.rb,
|
35
|
+
spec/pg/connection_spec.rb:
|
36
|
+
Improve Connection#copy_data:
|
37
|
+
- ensure and verify a clean exec status for each test case
|
38
|
+
- add error PG::NotAllCopyDataRetrieved and a spec for this case
|
39
|
+
- fix input/output naming in the specs
|
40
|
+
- use ArgumentError instead of PG::Error in case of non-COPY statement
|
41
|
+
[b0fd97e58a9a]
|
42
|
+
|
43
|
+
* History.rdoc, lib/pg.rb:
|
44
|
+
Bump VERSION to 0.16.1 and prepare History.rdoc for release.
|
45
|
+
[c2bbdcd4ef0f]
|
46
|
+
|
47
|
+
* lib/pg/connection.rb:
|
48
|
+
Fix examples of conn#copy_data and improve the documentation.
|
49
|
+
[53d027b0d064]
|
50
|
+
|
51
|
+
2013-09-07 Lars Kanis <lars@greiz-reinsdorf.de>
|
52
|
+
|
53
|
+
* ext/gvl_wrappers.h, ext/pg_connection.c:
|
54
|
+
Wrap PQisBusy to be called without GVL. It could trigger the notice
|
55
|
+
callback.
|
56
|
+
[d93b3ddc69ff]
|
57
|
+
|
58
|
+
* ext/gvl_wrappers.h, ext/pg_connection.c:
|
59
|
+
Wrap all PQsend* functions to be called without GVL.
|
60
|
+
|
61
|
+
These functions could trigger the notice callback when some notice
|
62
|
+
is yet in the buffer. The notice callback needs to be called without
|
63
|
+
GVL since it always reaquires the GLV. This fixes issue #171.
|
64
|
+
[1fd77c0a4cea]
|
65
|
+
|
66
|
+
2013-08-19 Lars Kanis <lars@greiz-reinsdorf.de>
|
67
|
+
|
68
|
+
* spec/pg/connection_spec.rb:
|
69
|
+
Add #copy_data case for non copy statement
|
70
|
+
[eea6da92b30a]
|
71
|
+
|
72
|
+
* ext/pg_connection.c:
|
73
|
+
Remove copy examples in favour of #copy_data
|
74
|
+
[c549f9878adf]
|
75
|
+
|
76
|
+
2013-08-18 Lars Kanis <lars@greiz-reinsdorf.de>
|
77
|
+
|
78
|
+
* merge tip
|
79
|
+
[90252df3c5c8]
|
80
|
+
|
81
|
+
2013-08-15 Lars Kanis <lars@greiz-reinsdorf.de>
|
82
|
+
|
83
|
+
* Rakefile.cross:
|
84
|
+
Use RbConfig::CONFIG['CC'] instead of ['host'] for determining cross
|
85
|
+
compilation platform.
|
86
|
+
|
87
|
+
This is 'i586-mingw32msvc-gcc' versus 'i586-pc-mingw32msvc'.
|
88
|
+
[fbee9586e8f7]
|
89
|
+
|
90
|
+
2013-08-18 Lars Kanis <lars@greiz-reinsdorf.de>
|
91
|
+
|
92
|
+
* lib/pg/connection.rb, spec/pg/connection_spec.rb:
|
93
|
+
Add PG::Connection#copy_data as a convenience method.
|
94
|
+
[5096385267ab]
|
95
|
+
|
96
|
+
* ext/pg_result.c:
|
97
|
+
Return self from PG::Result#check instead of nil. This allowes to
|
98
|
+
stack method calls.
|
99
|
+
[8255d4f73334]
|
100
|
+
|
101
|
+
2013-08-14 Lars Kanis <lars@greiz-reinsdorf.de>
|
102
|
+
|
103
|
+
* Gemfile, Rakefile:
|
104
|
+
Add Gemfile for compat with rake-compiler-dev-box.
|
105
|
+
|
106
|
+
Increase version of rake-compiler to 0.9. That is needed for the
|
107
|
+
x64-mingw32 build.
|
108
|
+
[355cce5c8566]
|
109
|
+
|
110
|
+
2013-08-13 Lars Kanis <lars@greiz-reinsdorf.de>
|
111
|
+
|
112
|
+
* ext/pg_connection.c:
|
113
|
+
Add usage examples for put_copy_data and get_copy_data.
|
114
|
+
[9959003173b4]
|
115
|
+
|
116
|
+
2013-08-11 Lars Kanis <lars@greiz-reinsdorf.de>
|
117
|
+
|
118
|
+
* Rakefile:
|
119
|
+
Add Lars Kanis to the list of developers in the gemspec.
|
120
|
+
[6d3d18452d99]
|
121
|
+
|
1
122
|
2013-07-23 Michael Granger <ged@FaerieMUD.org>
|
2
123
|
|
3
124
|
* .hgtags:
|
4
125
|
Added tag v0.16.0 for changeset def8f41a7672
|
5
|
-
[315fa9728831]
|
126
|
+
[315fa9728831]
|
6
127
|
|
7
128
|
* .hgsigs:
|
8
129
|
Added signature for changeset 4e0606f5f5aa
|
data/History.rdoc
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
== v0.17.0 [2013-09-15] Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
Bugfixes:
|
4
|
+
|
5
|
+
- Fix crash by calling PQsend* and PQisBusy without GVL (#171).
|
6
|
+
|
7
|
+
Enhancements:
|
8
|
+
|
9
|
+
- Add method PG::Connection#copy_data.
|
10
|
+
- Add a Gemfile to allow installation of dependencies with bundler.
|
11
|
+
- Add compatibility with rake-compiler-dev-box.
|
12
|
+
- Return self from PG::Result#check instead of nil. This allows
|
13
|
+
to stack method calls.
|
14
|
+
|
15
|
+
|
1
16
|
== v0.16.0 [2013-07-22] Michael Granger <ged@FaerieMUD.org>
|
2
17
|
|
3
18
|
Bugfixes:
|
data/Rakefile
CHANGED
@@ -38,6 +38,7 @@ CLEAN.include( PKGDIR.to_s, TMPDIR.to_s )
|
|
38
38
|
Hoe.plugin :mercurial
|
39
39
|
Hoe.plugin :signing
|
40
40
|
Hoe.plugin :deveiate
|
41
|
+
Hoe.plugin :bundler
|
41
42
|
|
42
43
|
Hoe.plugins.delete :rubyforge
|
43
44
|
Hoe.plugins.delete :compiler
|
@@ -54,9 +55,12 @@ $hoespec = Hoe.spec 'pg' do
|
|
54
55
|
self.extra_rdoc_files.include( 'ext/*.c' )
|
55
56
|
|
56
57
|
self.developer 'Michael Granger', 'ged@FaerieMUD.org'
|
58
|
+
self.developer 'Lars Kanis', 'lars@greiz-reinsdorf.de'
|
57
59
|
|
58
|
-
self.dependency 'rake-compiler', '~> 0.
|
59
|
-
self.dependency
|
60
|
+
self.dependency 'rake-compiler', '~> 0.9', :developer
|
61
|
+
self.dependency 'hoe', '~> 3.5.1', :developer
|
62
|
+
self.dependency 'hoe-deveiate', '~> 0.2', :developer
|
63
|
+
self.dependency 'hoe-bundler', '~> 1.0', :developer
|
60
64
|
|
61
65
|
self.spec_extras[:licenses] = ['BSD', 'Ruby', 'GPL']
|
62
66
|
self.spec_extras[:extensions] = [ 'ext/extconf.rb' ]
|
data/Rakefile.cross
CHANGED
@@ -72,7 +72,7 @@ class CrossLibrary < OpenStruct
|
|
72
72
|
self.host_platform = begin
|
73
73
|
config_file = YAML.load_file(File.expand_path("~/.rake-compiler/config.yml"))
|
74
74
|
_, rbfile = config_file.find{|key, fname| key.start_with?("rbconfig-#{for_platform}-") }
|
75
|
-
IO.read(rbfile).match(/CONFIG\["
|
75
|
+
IO.read(rbfile).match(/CONFIG\["CC"\] = "(.*)"/)[1].sub(/\-gcc/, '')
|
76
76
|
rescue
|
77
77
|
nil
|
78
78
|
end
|
data/ext/gvl_wrappers.h
CHANGED
@@ -168,7 +168,41 @@ void ubf_cancel_running_command(void *c);
|
|
168
168
|
|
169
169
|
#define FOR_EACH_PARAM_OF_PQnotifies(param)
|
170
170
|
|
171
|
-
|
171
|
+
#define FOR_EACH_PARAM_OF_PQsendQuery(param) \
|
172
|
+
param(PGconn *, conn)
|
173
|
+
|
174
|
+
#define FOR_EACH_PARAM_OF_PQsendQueryParams(param) \
|
175
|
+
param(PGconn *, conn) \
|
176
|
+
param(const char *, command) \
|
177
|
+
param(int, nParams) \
|
178
|
+
param(const Oid *, paramTypes) \
|
179
|
+
param(const char *const *, paramValues) \
|
180
|
+
param(const int *, paramLengths) \
|
181
|
+
param(const int *, paramFormats)
|
182
|
+
|
183
|
+
#define FOR_EACH_PARAM_OF_PQsendPrepare(param) \
|
184
|
+
param(PGconn *, conn) \
|
185
|
+
param(const char *, stmtName) \
|
186
|
+
param(const char *, query) \
|
187
|
+
param(int, nParams)
|
188
|
+
|
189
|
+
#define FOR_EACH_PARAM_OF_PQsendQueryPrepared(param) \
|
190
|
+
param(PGconn *, conn) \
|
191
|
+
param(const char *, stmtName) \
|
192
|
+
param(int, nParams) \
|
193
|
+
param(const char *const *, paramValues) \
|
194
|
+
param(const int *, paramLengths) \
|
195
|
+
param(const int *, paramFormats)
|
196
|
+
|
197
|
+
#define FOR_EACH_PARAM_OF_PQsendDescribePrepared(param) \
|
198
|
+
param(PGconn *, conn)
|
199
|
+
|
200
|
+
#define FOR_EACH_PARAM_OF_PQsendDescribePortal(param) \
|
201
|
+
param(PGconn *, conn)
|
202
|
+
|
203
|
+
#define FOR_EACH_PARAM_OF_PQisBusy(param)
|
204
|
+
|
205
|
+
/* function( name, cancel, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
172
206
|
#define FOR_EACH_BLOCKING_FUNCTION(function) \
|
173
207
|
function(PQconnectdb, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
|
174
208
|
function(PQconnectStart, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
|
@@ -186,7 +220,15 @@ void ubf_cancel_running_command(void *c);
|
|
186
220
|
function(PQputCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, nbytes) \
|
187
221
|
function(PQputCopyEnd, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, errormsg) \
|
188
222
|
function(PQgetCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, async) \
|
189
|
-
function(PQnotifies, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGnotify *, PGconn *, conn)
|
223
|
+
function(PQnotifies, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGnotify *, PGconn *, conn) \
|
224
|
+
function(PQsendQuery, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, query) \
|
225
|
+
function(PQsendQueryParams, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, resultFormat) \
|
226
|
+
function(PQsendPrepare, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const Oid *, paramTypes) \
|
227
|
+
function(PQsendQueryPrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, resultFormat) \
|
228
|
+
function(PQsendDescribePrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, stmt) \
|
229
|
+
function(PQsendDescribePortal, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, portal) \
|
230
|
+
function(PQisBusy, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, PGconn *, conn);
|
231
|
+
|
190
232
|
|
191
233
|
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
|
192
234
|
|
@@ -201,7 +243,7 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
|
|
201
243
|
#define FOR_EACH_PARAM_OF_notice_receiver_proxy(param) \
|
202
244
|
param(void *, arg)
|
203
245
|
|
204
|
-
/* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
246
|
+
/* function( name, cancel, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
205
247
|
#define FOR_EACH_CALLBACK_FUNCTION(function) \
|
206
248
|
function(notice_processor_proxy,, GVL_TYPE_VOID, void, const char *, message) \
|
207
249
|
function(notice_receiver_proxy,, GVL_TYPE_VOID, void, const PGresult *, result) \
|
data/ext/pg_connection.c
CHANGED
@@ -1610,7 +1610,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1610
1610
|
|
1611
1611
|
/* If called with no parameters, use PQsendQuery */
|
1612
1612
|
if(NIL_P(params)) {
|
1613
|
-
if(
|
1613
|
+
if(gvl_PQsendQuery(conn,StringValuePtr(command)) == 0) {
|
1614
1614
|
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1615
1615
|
rb_iv_set(error, "@connection", self);
|
1616
1616
|
rb_exc_raise(error);
|
@@ -1683,7 +1683,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1683
1683
|
paramFormats[i] = NUM2INT(param_format);
|
1684
1684
|
}
|
1685
1685
|
|
1686
|
-
result =
|
1686
|
+
result = gvl_PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1687
1687
|
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1688
1688
|
|
1689
1689
|
rb_gc_unregister_address(&gc_array);
|
@@ -1750,7 +1750,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1750
1750
|
paramTypes[i] = NUM2INT(param);
|
1751
1751
|
}
|
1752
1752
|
}
|
1753
|
-
result =
|
1753
|
+
result = gvl_PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
|
1754
1754
|
nParams, paramTypes);
|
1755
1755
|
|
1756
1756
|
xfree(paramTypes);
|
@@ -1868,7 +1868,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1868
1868
|
paramFormats[i] = NUM2INT(param_format);
|
1869
1869
|
}
|
1870
1870
|
|
1871
|
-
result =
|
1871
|
+
result = gvl_PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1872
1872
|
(const char * const *)paramValues, paramLengths, paramFormats,
|
1873
1873
|
resultFormat);
|
1874
1874
|
|
@@ -1899,7 +1899,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1899
1899
|
VALUE error;
|
1900
1900
|
PGconn *conn = pg_get_pgconn(self);
|
1901
1901
|
/* returns 0 on failure */
|
1902
|
-
if(
|
1902
|
+
if(gvl_PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
|
1903
1903
|
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1904
1904
|
rb_iv_set(error, "@connection", self);
|
1905
1905
|
rb_exc_raise(error);
|
@@ -1921,7 +1921,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
1921
1921
|
VALUE error;
|
1922
1922
|
PGconn *conn = pg_get_pgconn(self);
|
1923
1923
|
/* returns 0 on failure */
|
1924
|
-
if(
|
1924
|
+
if(gvl_PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
|
1925
1925
|
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1926
1926
|
rb_iv_set(error, "@connection", self);
|
1927
1927
|
rb_exc_raise(error);
|
@@ -1998,7 +1998,7 @@ static VALUE
|
|
1998
1998
|
pgconn_is_busy(self)
|
1999
1999
|
VALUE self;
|
2000
2000
|
{
|
2001
|
-
return
|
2001
|
+
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2002
2002
|
}
|
2003
2003
|
|
2004
2004
|
/*
|
@@ -2449,6 +2449,9 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
|
2449
2449
|
* is in nonblocking mode, and this command would block).
|
2450
2450
|
*
|
2451
2451
|
* Raises an exception if an error occurs.
|
2452
|
+
*
|
2453
|
+
* See also #copy_data.
|
2454
|
+
*
|
2452
2455
|
*/
|
2453
2456
|
static VALUE
|
2454
2457
|
pgconn_put_copy_data(self, buffer)
|
@@ -2513,6 +2516,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2513
2516
|
* if the copy is done, or +false+ if the call would
|
2514
2517
|
* block (only possible if _async_ is true).
|
2515
2518
|
*
|
2519
|
+
* See also #copy_data.
|
2520
|
+
*
|
2516
2521
|
*/
|
2517
2522
|
static VALUE
|
2518
2523
|
pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
@@ -2916,7 +2921,7 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2916
2921
|
static void *
|
2917
2922
|
get_result_readable(PGconn *conn)
|
2918
2923
|
{
|
2919
|
-
return
|
2924
|
+
return gvl_PQisBusy(conn) ? NULL : (void*)1;
|
2920
2925
|
}
|
2921
2926
|
|
2922
2927
|
|
data/ext/pg_result.c
CHANGED
@@ -74,7 +74,7 @@ pg_result_check( VALUE self )
|
|
74
74
|
#endif
|
75
75
|
case PGRES_EMPTY_QUERY:
|
76
76
|
case PGRES_COMMAND_OK:
|
77
|
-
return
|
77
|
+
return self;
|
78
78
|
case PGRES_BAD_RESPONSE:
|
79
79
|
case PGRES_FATAL_ERROR:
|
80
80
|
case PGRES_NONFATAL_ERROR:
|
@@ -97,7 +97,7 @@ pg_result_check( VALUE self )
|
|
97
97
|
rb_exc_raise( exception );
|
98
98
|
|
99
99
|
/* Not reached */
|
100
|
-
return
|
100
|
+
return self;
|
101
101
|
}
|
102
102
|
|
103
103
|
|
data/lib/2.0/pg_ext.so
CHANGED
Binary file
|
data/lib/pg.rb
CHANGED
@@ -19,11 +19,13 @@ end
|
|
19
19
|
module PG
|
20
20
|
|
21
21
|
# Library version
|
22
|
-
VERSION = '0.
|
22
|
+
VERSION = '0.17.0'
|
23
23
|
|
24
24
|
# VCS revision
|
25
25
|
REVISION = %q$Revision$
|
26
26
|
|
27
|
+
class NotAllCopyDataRetrieved < PG::Error
|
28
|
+
end
|
27
29
|
|
28
30
|
### Get the PG library version. If +include_buildnum+ is +true+, include the build ID.
|
29
31
|
def self::version_string( include_buildnum=false )
|
data/lib/pg/connection.rb
CHANGED
@@ -74,6 +74,91 @@ class PG::Connection
|
|
74
74
|
return connopts.join(' ')
|
75
75
|
end
|
76
76
|
|
77
|
+
# call-seq:
|
78
|
+
# conn.copy_data( sql ) {|sql_result| ... } -> PG::Result
|
79
|
+
#
|
80
|
+
# Execute a copy process for transfering data to or from the server.
|
81
|
+
#
|
82
|
+
# This issues the SQL COPY command via #exec. The response to this
|
83
|
+
# (if there is no error in the command) is a PG::Result object that
|
84
|
+
# is passed to the block, bearing a status code of PGRES_COPY_OUT or
|
85
|
+
# PGRES_COPY_IN (depending on the specified copy direction).
|
86
|
+
# The application should then use #put_copy_data or #get_copy_data
|
87
|
+
# to receive or transmit data rows and should return from the block
|
88
|
+
# when finished.
|
89
|
+
#
|
90
|
+
# #copy_data returns another PG::Result object when the data transfer
|
91
|
+
# is complete. An exception is raised if some problem was encountered,
|
92
|
+
# so it isn't required to make use of any of them.
|
93
|
+
# At this point further SQL commands can be issued via #exec.
|
94
|
+
# (It is not possible to execute other SQL commands using the same
|
95
|
+
# connection while the COPY operation is in progress.)
|
96
|
+
#
|
97
|
+
# This method ensures, that the copy process is properly terminated
|
98
|
+
# in case of client side or server side failures. Therefore, in case
|
99
|
+
# of blocking mode of operation, #copy_data is preferred to raw calls
|
100
|
+
# of #put_copy_data, #get_copy_data and #put_copy_end.
|
101
|
+
#
|
102
|
+
# Example with CSV input format:
|
103
|
+
# conn.exec "create table my_table (a text,b text,c text,d text,e text)"
|
104
|
+
# conn.copy_data "COPY my_table FROM STDOUT CSV" do
|
105
|
+
# conn.put_copy_data "some,csv,data,to,copy\n"
|
106
|
+
# conn.put_copy_data "more,csv,data,to,copy\n"
|
107
|
+
# end
|
108
|
+
# This creates +my_table+ and inserts two rows.
|
109
|
+
#
|
110
|
+
# Example with CSV output format:
|
111
|
+
# conn.copy_data "COPY my_table TO STDOUT CSV" do
|
112
|
+
# while row=conn.get_copy_data
|
113
|
+
# p row
|
114
|
+
# end
|
115
|
+
# end
|
116
|
+
# This prints all rows of +my_table+ to stdout:
|
117
|
+
# "some,csv,data,to,copy\n"
|
118
|
+
# "more,csv,data,to,copy\n"
|
119
|
+
def copy_data( sql )
|
120
|
+
res = exec( sql )
|
121
|
+
|
122
|
+
case res.result_status
|
123
|
+
when PGRES_COPY_IN
|
124
|
+
begin
|
125
|
+
yield res
|
126
|
+
rescue Exception => err
|
127
|
+
errmsg = "%s while copy data: %s" % [ err.class.name, err.message ]
|
128
|
+
put_copy_end( errmsg )
|
129
|
+
get_result
|
130
|
+
raise
|
131
|
+
else
|
132
|
+
put_copy_end
|
133
|
+
get_last_result
|
134
|
+
end
|
135
|
+
|
136
|
+
when PGRES_COPY_OUT
|
137
|
+
begin
|
138
|
+
yield res
|
139
|
+
rescue Exception => err
|
140
|
+
cancel
|
141
|
+
while get_copy_data
|
142
|
+
end
|
143
|
+
while get_result
|
144
|
+
end
|
145
|
+
raise
|
146
|
+
else
|
147
|
+
res = get_last_result
|
148
|
+
if res.result_status != PGRES_COMMAND_OK
|
149
|
+
while get_copy_data
|
150
|
+
end
|
151
|
+
while get_result
|
152
|
+
end
|
153
|
+
raise PG::NotAllCopyDataRetrieved, "Not all COPY data retrieved"
|
154
|
+
end
|
155
|
+
res
|
156
|
+
end
|
157
|
+
|
158
|
+
else
|
159
|
+
raise ArgumentError, "SQL command is no COPY statement: #{sql}"
|
160
|
+
end
|
161
|
+
end
|
77
162
|
|
78
163
|
# Backward-compatibility aliases for stuff that's moved into PG.
|
79
164
|
class << self
|
data/spec/lib/helpers.rb
CHANGED
@@ -254,6 +254,12 @@ module PG::TestingHelpers
|
|
254
254
|
conn_name.should include(app_name[-10..-1])
|
255
255
|
conn_name.length.should <= 64
|
256
256
|
end
|
257
|
+
|
258
|
+
# Ensure the connection is in a clean execution status.
|
259
|
+
def verify_clean_exec_status
|
260
|
+
@conn.send_query( "VALUES (1)" )
|
261
|
+
@conn.get_last_result.values.should == [["1"]]
|
262
|
+
end
|
257
263
|
end
|
258
264
|
|
259
265
|
|
data/spec/pg/connection_spec.rb
CHANGED
@@ -457,6 +457,101 @@ describe PG::Connection do
|
|
457
457
|
rval.should include( '5678', '1234' )
|
458
458
|
end
|
459
459
|
|
460
|
+
it "can process #copy_data output queries" do
|
461
|
+
rows = []
|
462
|
+
res2 = @conn.copy_data( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" ) do |res|
|
463
|
+
res.result_status.should == PG::PGRES_COPY_OUT
|
464
|
+
res.nfields.should == 1
|
465
|
+
while row=@conn.get_copy_data
|
466
|
+
rows << row
|
467
|
+
end
|
468
|
+
end
|
469
|
+
rows.should == ["1\n", "2\n"]
|
470
|
+
res2.result_status.should == PG::PGRES_COMMAND_OK
|
471
|
+
verify_clean_exec_status
|
472
|
+
end
|
473
|
+
|
474
|
+
it "can handle incomplete #copy_data output queries" do
|
475
|
+
expect {
|
476
|
+
@conn.copy_data( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" ) do |res|
|
477
|
+
@conn.get_copy_data
|
478
|
+
end
|
479
|
+
}.to raise_error(PG::NotAllCopyDataRetrieved, /Not all/)
|
480
|
+
verify_clean_exec_status
|
481
|
+
end
|
482
|
+
|
483
|
+
it "can handle client errors in #copy_data for output" do
|
484
|
+
expect {
|
485
|
+
@conn.copy_data( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" ) do
|
486
|
+
raise "boom"
|
487
|
+
end
|
488
|
+
}.to raise_error(RuntimeError, "boom")
|
489
|
+
verify_clean_exec_status
|
490
|
+
end
|
491
|
+
|
492
|
+
it "can handle server errors in #copy_data for output" do
|
493
|
+
@conn.exec "ROLLBACK"
|
494
|
+
@conn.transaction do
|
495
|
+
@conn.exec( "CREATE FUNCTION errfunc() RETURNS int AS $$ BEGIN RAISE 'test-error'; END; $$ LANGUAGE plpgsql;" )
|
496
|
+
expect {
|
497
|
+
@conn.copy_data( "COPY (SELECT errfunc()) TO STDOUT" ) do |res|
|
498
|
+
while @conn.get_copy_data
|
499
|
+
end
|
500
|
+
end
|
501
|
+
}.to raise_error(PG::Error, /test-error/)
|
502
|
+
end
|
503
|
+
verify_clean_exec_status
|
504
|
+
end
|
505
|
+
|
506
|
+
it "can process #copy_data input queries" do
|
507
|
+
@conn.exec( "CREATE TEMP TABLE copytable (col1 TEXT)" )
|
508
|
+
res2 = @conn.copy_data( "COPY copytable FROM STDOUT" ) do |res|
|
509
|
+
res.result_status.should == PG::PGRES_COPY_IN
|
510
|
+
res.nfields.should == 1
|
511
|
+
@conn.put_copy_data "1\n"
|
512
|
+
@conn.put_copy_data "2\n"
|
513
|
+
end
|
514
|
+
res2.result_status.should == PG::PGRES_COMMAND_OK
|
515
|
+
|
516
|
+
verify_clean_exec_status
|
517
|
+
|
518
|
+
res = @conn.exec( "SELECT * FROM copytable ORDER BY col1" )
|
519
|
+
res.values.should == [["1"], ["2"]]
|
520
|
+
end
|
521
|
+
|
522
|
+
it "can handle client errors in #copy_data for input" do
|
523
|
+
@conn.exec "ROLLBACK"
|
524
|
+
@conn.transaction do
|
525
|
+
@conn.exec( "CREATE TEMP TABLE copytable (col1 TEXT)" )
|
526
|
+
expect {
|
527
|
+
@conn.copy_data( "COPY copytable FROM STDOUT" ) do |res|
|
528
|
+
raise "boom"
|
529
|
+
end
|
530
|
+
}.to raise_error(RuntimeError, "boom")
|
531
|
+
end
|
532
|
+
verify_clean_exec_status
|
533
|
+
end
|
534
|
+
|
535
|
+
it "can handle server errors in #copy_data for input" do
|
536
|
+
@conn.exec "ROLLBACK"
|
537
|
+
@conn.transaction do
|
538
|
+
@conn.exec( "CREATE TEMP TABLE copytable (col1 INT)" )
|
539
|
+
expect {
|
540
|
+
@conn.copy_data( "COPY copytable FROM STDOUT" ) do |res|
|
541
|
+
@conn.put_copy_data "xyz\n"
|
542
|
+
end
|
543
|
+
}.to raise_error(PG::Error, /invalid input syntax for integer/)
|
544
|
+
end
|
545
|
+
verify_clean_exec_status
|
546
|
+
end
|
547
|
+
|
548
|
+
it "should raise an error for non copy statements in #copy_data" do
|
549
|
+
expect {
|
550
|
+
@conn.copy_data( "SELECT 1" ){}
|
551
|
+
}.to raise_error(ArgumentError, /no COPY/)
|
552
|
+
|
553
|
+
verify_clean_exec_status
|
554
|
+
end
|
460
555
|
|
461
556
|
it "correctly finishes COPY queries passed to #async_exec" do
|
462
557
|
@conn.async_exec( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" )
|
metadata
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: x64-mingw32
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
8
|
+
- Lars Kanis
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain:
|
@@ -30,7 +31,7 @@ cert_chain:
|
|
30
31
|
mMFp4kPUHbWOqCp2mz9gCA==
|
31
32
|
-----END CERTIFICATE-----
|
32
33
|
|
33
|
-
date: 2013-
|
34
|
+
date: 2013-09-16 00:00:00 Z
|
34
35
|
dependencies:
|
35
36
|
- !ruby/object:Gem::Dependency
|
36
37
|
name: hoe-mercurial
|
@@ -69,29 +70,39 @@ dependencies:
|
|
69
70
|
requirements:
|
70
71
|
- - ~>
|
71
72
|
- !ruby/object:Gem::Version
|
72
|
-
version: "0.
|
73
|
+
version: "0.9"
|
73
74
|
type: :development
|
74
75
|
version_requirements: *id004
|
75
76
|
- !ruby/object:Gem::Dependency
|
76
|
-
name: hoe
|
77
|
+
name: hoe
|
77
78
|
prerelease: false
|
78
79
|
requirement: &id005 !ruby/object:Gem::Requirement
|
79
80
|
requirements:
|
80
81
|
- - ~>
|
81
82
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
83
|
+
version: 3.5.1
|
83
84
|
type: :development
|
84
85
|
version_requirements: *id005
|
85
86
|
- !ruby/object:Gem::Dependency
|
86
|
-
name: hoe
|
87
|
+
name: hoe-deveiate
|
87
88
|
prerelease: false
|
88
89
|
requirement: &id006 !ruby/object:Gem::Requirement
|
89
90
|
requirements:
|
90
91
|
- - ~>
|
91
92
|
- !ruby/object:Gem::Version
|
92
|
-
version: "
|
93
|
+
version: "0.2"
|
93
94
|
type: :development
|
94
95
|
version_requirements: *id006
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: hoe-bundler
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "1.0"
|
104
|
+
type: :development
|
105
|
+
version_requirements: *id007
|
95
106
|
description: |-
|
96
107
|
Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
|
97
108
|
|
@@ -114,6 +125,7 @@ description: |-
|
|
114
125
|
end
|
115
126
|
email:
|
116
127
|
- ged@FaerieMUD.org
|
128
|
+
- lars@greiz-reinsdorf.de
|
117
129
|
executables: []
|
118
130
|
|
119
131
|
extensions: []
|
metadata.gz.sig
CHANGED
Binary file
|