pg 0.16.0-x64-mingw32 → 0.17.0-x64-mingw32

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- data.tar.gz: ed7bab2dd53a3ae63b96d2e43b0b94438c1517fb
4
- metadata.gz: dacd22ae85fe3a798d05c1b5b6c2e8544786c7e5
3
+ metadata.gz: 21f53fb93db689d13bbec315cbf5190e22581120
4
+ data.tar.gz: 59fe2cf2c7bedfe9d1295779e434e52812a0cb26
5
5
  SHA512:
6
- data.tar.gz: 50b8196d92f9a8ae7dcaaec73e68fca6d849350b8a3db3826ae7e950e1c1bb4820e1b12d73b65875a6224184c7c0c42890076a2220a4b4159a7c778b43014b86
7
- metadata.gz: a156df14e7ab2ae58d3ed2bc5c0326ffb07ebe968cd843c8e55d48449609c2a8e93f064fbbdd2ee62661ed2e91dab077bff0e03ebc08658bdd0144c03530fb7b
6
+ metadata.gz: 79f561112dee71eec9cfeb84f94a253f1ac2c9cdfc1e5227a7c96ea1e07a37940a6c35be804d425ebe282cd7a3cf8e2ddfd9fff20ccf67aa5ec099fd2afd1634
7
+ data.tar.gz: 26ec759a2af8b649ea4a11b3521a99536f2af838da7e94ea77b7c2a4916bcbd209876b58fc50fa3990e7f15fd9e060a8706e7bdcddd4191d6e5168df6765cf32
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] [tip]
126
+ [315fa9728831]
6
127
 
7
128
  * .hgsigs:
8
129
  Added signature for changeset 4e0606f5f5aa
@@ -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.8', :developer
59
- self.dependency 'hoe-deveiate', '~> 0.2', :developer
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' ]
@@ -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\["host"\] = "(.*)"/)[1]
75
+ IO.read(rbfile).match(/CONFIG\["CC"\] = "(.*)"/)[1].sub(/\-gcc/, '')
76
76
  rescue
77
77
  nil
78
78
  end
@@ -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
- /* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
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) \
@@ -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(PQsendQuery(conn,StringValuePtr(command)) == 0) {
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 = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
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 = PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
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 = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
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(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
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(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
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 PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
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 PQisBusy(conn) ? NULL : (void*)1;
2924
+ return gvl_PQisBusy(conn) ? NULL : (void*)1;
2920
2925
  }
2921
2926
 
2922
2927
 
@@ -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 Qnil;
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 Qnil;
100
+ return self;
101
101
  }
102
102
 
103
103
 
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.16.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 )
@@ -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
@@ -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
 
@@ -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.16.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-07-23 00:00:00 Z
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.8"
73
+ version: "0.9"
73
74
  type: :development
74
75
  version_requirements: *id004
75
76
  - !ruby/object:Gem::Dependency
76
- name: hoe-deveiate
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: "0.2"
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: "3.6"
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