pg 0.15.0.pre.454-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.gemtest +0 -0
  3. data/BSDL +22 -0
  4. data/ChangeLog +2945 -0
  5. data/Contributors.rdoc +46 -0
  6. data/History.rdoc +205 -0
  7. data/LICENSE +56 -0
  8. data/Manifest.txt +53 -0
  9. data/POSTGRES +23 -0
  10. data/README-OS_X.rdoc +68 -0
  11. data/README-Windows.rdoc +67 -0
  12. data/README.ja.rdoc +14 -0
  13. data/README.rdoc +111 -0
  14. data/Rakefile +156 -0
  15. data/Rakefile.cross +271 -0
  16. data/ext/extconf.rb +91 -0
  17. data/ext/gvl_wrappers.c +13 -0
  18. data/ext/gvl_wrappers.h +185 -0
  19. data/ext/pg.c +525 -0
  20. data/ext/pg.h +126 -0
  21. data/ext/pg_connection.c +3600 -0
  22. data/ext/pg_result.c +939 -0
  23. data/ext/vc/pg.sln +26 -0
  24. data/ext/vc/pg_18/pg.vcproj +216 -0
  25. data/ext/vc/pg_19/pg_19.vcproj +209 -0
  26. data/lib/2.0/pg_ext.so +0 -0
  27. data/lib/pg.rb +52 -0
  28. data/lib/pg/connection.rb +71 -0
  29. data/lib/pg/constants.rb +11 -0
  30. data/lib/pg/exceptions.rb +11 -0
  31. data/lib/pg/result.rb +16 -0
  32. data/sample/array_insert.rb +20 -0
  33. data/sample/async_api.rb +106 -0
  34. data/sample/async_copyto.rb +39 -0
  35. data/sample/async_mixed.rb +56 -0
  36. data/sample/check_conn.rb +21 -0
  37. data/sample/copyfrom.rb +81 -0
  38. data/sample/copyto.rb +19 -0
  39. data/sample/cursor.rb +21 -0
  40. data/sample/disk_usage_report.rb +186 -0
  41. data/sample/issue-119.rb +94 -0
  42. data/sample/losample.rb +69 -0
  43. data/sample/minimal-testcase.rb +17 -0
  44. data/sample/notify_wait.rb +72 -0
  45. data/sample/pg_statistics.rb +294 -0
  46. data/sample/replication_monitor.rb +231 -0
  47. data/sample/test_binary_values.rb +33 -0
  48. data/sample/wal_shipper.rb +434 -0
  49. data/sample/warehouse_partitions.rb +320 -0
  50. data/spec/data/expected_trace.out +26 -0
  51. data/spec/data/random_binary_data +0 -0
  52. data/spec/lib/helpers.rb +279 -0
  53. data/spec/pg/connection_spec.rb +1013 -0
  54. data/spec/pg/result_spec.rb +278 -0
  55. data/spec/pg_spec.rb +31 -0
  56. metadata +275 -0
  57. metadata.gz.sig +0 -0
@@ -0,0 +1,126 @@
1
+ #ifndef __pg_h
2
+ #define __pg_h
3
+
4
+ #ifdef RUBY_EXTCONF_H
5
+ # include RUBY_EXTCONF_H
6
+ #endif
7
+
8
+ /* System headers */
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <sys/types.h>
12
+ #if defined(HAVE_UNISTD_H) && !defined(_WIN32)
13
+ # include <unistd.h>
14
+ #endif /* HAVE_UNISTD_H */
15
+
16
+ /* Ruby headers */
17
+ #include "ruby.h"
18
+ #ifdef HAVE_RUBY_ST_H
19
+ # include "ruby/st.h"
20
+ #elif HAVE_ST_H
21
+ # include "st.h"
22
+ #endif
23
+
24
+ #if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
25
+ # include "ruby/encoding.h"
26
+ # define M17N_SUPPORTED
27
+ # define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), pg_enc_get_index((index_holder)))
28
+ # ifdef HAVE_RB_ENCDB_ALIAS
29
+ extern int rb_encdb_alias(const char *, const char *);
30
+ # define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
31
+ # elif HAVE_RB_ENC_ALIAS
32
+ extern int rb_enc_alias(const char *, const char *);
33
+ # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
34
+ # else
35
+ extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
36
+ # define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
37
+ # endif
38
+ #else
39
+ # define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
40
+ #endif
41
+
42
+ #if RUBY_VM != 1
43
+ # define RUBY_18_COMPAT
44
+ #endif
45
+
46
+ #ifndef RARRAY_LEN
47
+ # define RARRAY_LEN(x) RARRAY((x))->len
48
+ #endif /* RARRAY_LEN */
49
+
50
+ #ifndef RSTRING_LEN
51
+ # define RSTRING_LEN(x) RSTRING((x))->len
52
+ #endif /* RSTRING_LEN */
53
+
54
+ #ifndef RSTRING_PTR
55
+ # define RSTRING_PTR(x) RSTRING((x))->ptr
56
+ #endif /* RSTRING_PTR */
57
+
58
+ #ifndef StringValuePtr
59
+ # define StringValuePtr(x) STR2CSTR(x)
60
+ #endif /* StringValuePtr */
61
+
62
+ #ifdef RUBY_18_COMPAT
63
+ # define rb_io_stdio_file GetWriteFile
64
+ # include "rubyio.h"
65
+ #else
66
+ # include "ruby/io.h"
67
+ #endif
68
+
69
+ /* PostgreSQL headers */
70
+ #include "libpq-fe.h"
71
+ #include "libpq/libpq-fs.h" /* large-object interface */
72
+ #include "pg_config_manual.h"
73
+
74
+ #if defined(_WIN32)
75
+ # include <fcntl.h>
76
+ __declspec(dllexport)
77
+ typedef long suseconds_t;
78
+ #endif
79
+
80
+ #include "gvl_wrappers.h"
81
+
82
+ /***************************************************************************
83
+ * Globals
84
+ **************************************************************************/
85
+
86
+ extern VALUE rb_mPG;
87
+ extern VALUE rb_ePGerror;
88
+ extern VALUE rb_mPGconstants;
89
+ extern VALUE rb_cPGconn;
90
+ extern VALUE rb_cPGresult;
91
+
92
+
93
+ /***************************************************************************
94
+ * MACROS
95
+ **************************************************************************/
96
+
97
+ #define UNUSED(x) ((void)(x))
98
+ #define SINGLETON_ALIAS(klass,new,old) rb_define_alias(rb_singleton_class((klass)),(new),(old))
99
+
100
+
101
+ /***************************************************************************
102
+ * PROTOTYPES
103
+ **************************************************************************/
104
+ void Init_pg_ext _(( void ));
105
+
106
+ void init_pg_connection _(( void ));
107
+ void init_pg_result _(( void ));
108
+
109
+ PGconn *pg_get_pgconn _(( VALUE ));
110
+
111
+ VALUE pg_new_result _(( PGresult *, VALUE ));
112
+ VALUE pg_result_check _(( VALUE ));
113
+ VALUE pg_result_clear _(( VALUE ));
114
+
115
+ #ifdef M17N_SUPPORTED
116
+ rb_encoding * pg_get_pg_encoding_as_rb_encoding _(( int ));
117
+ rb_encoding * pg_get_pg_encname_as_rb_encoding _(( const char * ));
118
+ const char * pg_get_rb_encoding_as_pg_encoding _(( rb_encoding * ));
119
+ int pg_enc_get_index _(( VALUE ));
120
+ rb_encoding *pg_conn_enc_get _(( PGconn * ));
121
+ #endif /* M17N_SUPPORTED */
122
+
123
+ void notice_receiver_proxy(void *arg, const PGresult *result);
124
+ void notice_processor_proxy(void *arg, const char *message);
125
+
126
+ #endif /* end __pg_h */
@@ -0,0 +1,3600 @@
1
+ /*
2
+ * pg_connection.c - PG::Connection class extension
3
+ * $Id$
4
+ *
5
+ */
6
+
7
+ #include "pg.h"
8
+
9
+
10
+ /********************************************************************
11
+ *
12
+ * Document-class: PG::Connection
13
+ *
14
+ * The class to access PostgreSQL RDBMS, based on the libpq interface,
15
+ * provides convenient OO methods to interact with PostgreSQL.
16
+ *
17
+ * For example, to send query to the database on the localhost:
18
+ * require 'pg'
19
+ * conn = PG::Connection.open(:dbname => 'test')
20
+ * res = conn.exec('SELECT $1 AS a, $2 AS b, $3 AS c',[1, 2, nil])
21
+ * # Equivalent to:
22
+ * # res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
23
+ *
24
+ * See the PG::Result class for information on working with the results of a query.
25
+ *
26
+ */
27
+ VALUE rb_cPGconn;
28
+
29
+ static PQnoticeReceiver default_notice_receiver = NULL;
30
+ static PQnoticeProcessor default_notice_processor = NULL;
31
+
32
+ static PGconn *pgconn_check( VALUE );
33
+ static VALUE pgconn_finish( VALUE );
34
+ #ifdef M17N_SUPPORTED
35
+ static VALUE pgconn_set_default_encoding( VALUE self );
36
+ #endif
37
+
38
+ #ifndef HAVE_RB_THREAD_FD_SELECT
39
+ #define rb_fdset_t fd_set
40
+ #define rb_fd_init(f)
41
+ #define rb_fd_zero(f) FD_ZERO(f)
42
+ #define rb_fd_set(n, f) FD_SET(n, f)
43
+ #define rb_fd_term(f)
44
+ #define rb_thread_fd_select rb_thread_select
45
+ #endif
46
+
47
+ /*
48
+ * Global functions
49
+ */
50
+
51
+ /*
52
+ * Fetch the data pointer and check it for sanity.
53
+ */
54
+ PGconn *
55
+ pg_get_pgconn( VALUE self )
56
+ {
57
+ PGconn *conn = pgconn_check( self );
58
+
59
+ if ( !conn )
60
+ rb_raise( rb_ePGerror, "connection is closed" );
61
+
62
+ return conn;
63
+ }
64
+
65
+
66
+ /*
67
+ * Close the associated socket IO object if there is one.
68
+ */
69
+ void
70
+ pgconn_close_socket_io( VALUE self )
71
+ {
72
+ VALUE socket_io = rb_iv_get( self, "@socket_io" );
73
+ int ruby_sd;
74
+
75
+ if ( RTEST(socket_io) ) {
76
+ #if defined(_WIN32) && defined(HAVE_RB_W32_WRAP_IO_HANDLE)
77
+ ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
78
+ if( rb_w32_unwrap_io_handle(ruby_sd) ){
79
+ rb_raise(rb_ePGerror, "Could not unwrap win32 socket handle");
80
+ }
81
+ #endif
82
+ rb_funcall( socket_io, rb_intern("close"), 0 );
83
+ }
84
+
85
+ rb_iv_set( self, "@socket_io", Qnil );
86
+ }
87
+
88
+
89
+ /*
90
+ * Allocation/
91
+ */
92
+
93
+ /*
94
+ * Object validity checker. Returns the data pointer.
95
+ */
96
+ static PGconn *
97
+ pgconn_check( VALUE self ) {
98
+
99
+ Check_Type( self, T_DATA );
100
+
101
+ if ( !rb_obj_is_kind_of(self, rb_cPGconn) ) {
102
+ rb_raise( rb_eTypeError, "wrong argument type %s (expected PG::Connection)",
103
+ rb_obj_classname( self ) );
104
+ }
105
+
106
+ return DATA_PTR( self );
107
+ }
108
+
109
+
110
+ /*
111
+ * GC Free function
112
+ */
113
+ static void
114
+ pgconn_gc_free( PGconn *conn )
115
+ {
116
+ if (conn != NULL)
117
+ PQfinish( conn );
118
+ }
119
+
120
+
121
+ /**************************************************************************
122
+ * Class Methods
123
+ **************************************************************************/
124
+
125
+ /*
126
+ * Document-method: allocate
127
+ *
128
+ * call-seq:
129
+ * PG::Connection.allocate -> conn
130
+ */
131
+ static VALUE
132
+ pgconn_s_allocate( VALUE klass )
133
+ {
134
+ return Data_Wrap_Struct( klass, NULL, pgconn_gc_free, NULL );
135
+ }
136
+
137
+
138
+ /*
139
+ * Document-method: new
140
+ *
141
+ * call-seq:
142
+ * PG::Connection.new -> conn
143
+ * PG::Connection.new(connection_hash) -> conn
144
+ * PG::Connection.new(connection_string) -> conn
145
+ * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
146
+ *
147
+ * Create a connection to the specified server.
148
+ *
149
+ * [+host+]
150
+ * server hostname
151
+ * [+hostaddr+]
152
+ * server address (avoids hostname lookup, overrides +host+)
153
+ * [+port+]
154
+ * server port number
155
+ * [+dbname+]
156
+ * connecting database name
157
+ * [+user+]
158
+ * login user name
159
+ * [+password+]
160
+ * login password
161
+ * [+connect_timeout+]
162
+ * maximum time to wait for connection to succeed
163
+ * [+options+]
164
+ * backend options
165
+ * [+tty+]
166
+ * (ignored in newer versions of PostgreSQL)
167
+ * [+sslmode+]
168
+ * (disable|allow|prefer|require)
169
+ * [+krbsrvname+]
170
+ * kerberos service name
171
+ * [+gsslib+]
172
+ * GSS library to use for GSSAPI authentication
173
+ * [+service+]
174
+ * service name to use for additional parameters
175
+ *
176
+ * Examples:
177
+ *
178
+ * # Connect using all defaults
179
+ * PG::Connection.new
180
+ *
181
+ * # As a Hash
182
+ * PG::Connection.new( :dbname => 'test', :port => 5432 )
183
+ *
184
+ * # As a String
185
+ * PG::Connection.new( "dbname=test port=5432" )
186
+ *
187
+ * # As an Array
188
+ * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
189
+ *
190
+ * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
191
+ * connection will have its +client_encoding+ set accordingly.
192
+ *
193
+ * Raises a PG::Error if the connection fails.
194
+ */
195
+ static VALUE
196
+ pgconn_init(int argc, VALUE *argv, VALUE self)
197
+ {
198
+ PGconn *conn = NULL;
199
+ VALUE conninfo;
200
+ VALUE error;
201
+
202
+ conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
203
+ conn = PQconnectdb(StringValuePtr(conninfo));
204
+
205
+ if(conn == NULL)
206
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
207
+
208
+ Check_Type(self, T_DATA);
209
+ DATA_PTR(self) = conn;
210
+
211
+ if (PQstatus(conn) == CONNECTION_BAD) {
212
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
213
+ rb_iv_set(error, "@connection", self);
214
+ rb_exc_raise(error);
215
+ }
216
+
217
+ #ifdef M17N_SUPPORTED
218
+ pgconn_set_default_encoding( self );
219
+ #endif
220
+
221
+ if (rb_block_given_p()) {
222
+ return rb_ensure(rb_yield, self, pgconn_finish, self);
223
+ }
224
+ return self;
225
+ }
226
+
227
+ /*
228
+ * call-seq:
229
+ * PG::Connection.connect_start(connection_hash) -> conn
230
+ * PG::Connection.connect_start(connection_string) -> conn
231
+ * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
232
+ *
233
+ * This is an asynchronous version of PG::Connection.connect().
234
+ *
235
+ * Use #connect_poll to poll the status of the connection.
236
+ *
237
+ * NOTE: this does *not* set the connection's +client_encoding+ for you if
238
+ * Encoding.default_internal is set. To set it after the connection is established,
239
+ * call #internal_encoding=. You can also set it automatically by setting
240
+ * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
241
+ *
242
+ */
243
+ static VALUE
244
+ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
245
+ {
246
+ PGconn *conn = NULL;
247
+ VALUE rb_conn;
248
+ VALUE conninfo;
249
+ VALUE error;
250
+
251
+ /*
252
+ * PG::Connection.connect_start must act as both alloc() and initialize()
253
+ * because it is not invoked by calling new().
254
+ */
255
+ rb_conn = pgconn_s_allocate( klass );
256
+ conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
257
+ conn = PQconnectStart( StringValuePtr(conninfo) );
258
+
259
+ if( conn == NULL )
260
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
261
+
262
+ Check_Type(rb_conn, T_DATA);
263
+ DATA_PTR(rb_conn) = conn;
264
+
265
+ if ( PQstatus(conn) == CONNECTION_BAD ) {
266
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
267
+ rb_iv_set(error, "@connection", rb_conn);
268
+ rb_exc_raise(error);
269
+ }
270
+
271
+ if ( rb_block_given_p() ) {
272
+ return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
273
+ }
274
+ return rb_conn;
275
+ }
276
+
277
+ #ifdef HAVE_PQPING
278
+ /*
279
+ * call-seq:
280
+ * PG::Connection.ping(connection_hash) -> Fixnum
281
+ * PG::Connection.ping(connection_string) -> Fixnum
282
+ * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Fixnum
283
+ *
284
+ * Check server status.
285
+ *
286
+ * Returns one of:
287
+ * [+PQPING_OK+]
288
+ * server is accepting connections
289
+ * [+PQPING_REJECT+]
290
+ * server is alive but rejecting connections
291
+ * [+PQPING_NO_RESPONSE+]
292
+ * could not establish connection
293
+ * [+PQPING_NO_ATTEMPT+]
294
+ * connection not attempted (bad params)
295
+ */
296
+ static VALUE
297
+ pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
298
+ {
299
+ PGPing ping;
300
+ VALUE conninfo;
301
+
302
+ conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
303
+ ping = PQping( StringValuePtr(conninfo) );
304
+
305
+ return INT2FIX((int)ping);
306
+ }
307
+ #endif
308
+
309
+ /*
310
+ * call-seq:
311
+ * PG::Connection.conndefaults() -> Array
312
+ *
313
+ * Returns an array of hashes. Each hash has the keys:
314
+ * [+:keyword+]
315
+ * the name of the option
316
+ * [+:envvar+]
317
+ * the environment variable to fall back to
318
+ * [+:compiled+]
319
+ * the compiled in option as a secondary fallback
320
+ * [+:val+]
321
+ * the option's current value, or +nil+ if not known
322
+ * [+:label+]
323
+ * the label for the field
324
+ * [+:dispchar+]
325
+ * "" for normal, "D" for debug, and "*" for password
326
+ * [+:dispsize+]
327
+ * field size
328
+ */
329
+ static VALUE
330
+ pgconn_s_conndefaults(VALUE self)
331
+ {
332
+ PQconninfoOption *options = PQconndefaults();
333
+ VALUE ary = rb_ary_new();
334
+ VALUE hash;
335
+ int i = 0;
336
+
337
+ UNUSED( self );
338
+
339
+ for(i = 0; options[i].keyword != NULL; i++) {
340
+ hash = rb_hash_new();
341
+ if(options[i].keyword)
342
+ rb_hash_aset(hash, ID2SYM(rb_intern("keyword")), rb_str_new2(options[i].keyword));
343
+ if(options[i].envvar)
344
+ rb_hash_aset(hash, ID2SYM(rb_intern("envvar")), rb_str_new2(options[i].envvar));
345
+ if(options[i].compiled)
346
+ rb_hash_aset(hash, ID2SYM(rb_intern("compiled")), rb_str_new2(options[i].compiled));
347
+ if(options[i].val)
348
+ rb_hash_aset(hash, ID2SYM(rb_intern("val")), rb_str_new2(options[i].val));
349
+ if(options[i].label)
350
+ rb_hash_aset(hash, ID2SYM(rb_intern("label")), rb_str_new2(options[i].label));
351
+ if(options[i].dispchar)
352
+ rb_hash_aset(hash, ID2SYM(rb_intern("dispchar")), rb_str_new2(options[i].dispchar));
353
+ rb_hash_aset(hash, ID2SYM(rb_intern("dispsize")), INT2NUM(options[i].dispsize));
354
+ rb_ary_push(ary, hash);
355
+ }
356
+ PQconninfoFree(options);
357
+ return ary;
358
+ }
359
+
360
+
361
+ /*
362
+ * call-seq:
363
+ * PG::Connection.encrypt_password( password, username ) -> String
364
+ *
365
+ * This function is intended to be used by client applications that
366
+ * send commands like: +ALTER USER joe PASSWORD 'pwd'+.
367
+ * The arguments are the cleartext password, and the SQL name
368
+ * of the user it is for.
369
+ *
370
+ * Return value is the encrypted password.
371
+ */
372
+ static VALUE
373
+ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
374
+ {
375
+ char *encrypted = NULL;
376
+ VALUE rval = Qnil;
377
+
378
+ UNUSED( self );
379
+
380
+ Check_Type(password, T_STRING);
381
+ Check_Type(username, T_STRING);
382
+
383
+ encrypted = PQencryptPassword(StringValuePtr(password), StringValuePtr(username));
384
+ rval = rb_str_new2( encrypted );
385
+ PQfreemem( encrypted );
386
+
387
+ OBJ_INFECT( rval, password );
388
+ OBJ_INFECT( rval, username );
389
+
390
+ return rval;
391
+ }
392
+
393
+
394
+ /**************************************************************************
395
+ * PG::Connection INSTANCE METHODS
396
+ **************************************************************************/
397
+
398
+ /*
399
+ * call-seq:
400
+ * conn.connect_poll() -> Fixnum
401
+ *
402
+ * Returns one of:
403
+ * [+PGRES_POLLING_READING+]
404
+ * wait until the socket is ready to read
405
+ * [+PGRES_POLLING_WRITING+]
406
+ * wait until the socket is ready to write
407
+ * [+PGRES_POLLING_FAILED+]
408
+ * the asynchronous connection has failed
409
+ * [+PGRES_POLLING_OK+]
410
+ * the asynchronous connection is ready
411
+ *
412
+ * Example:
413
+ * conn = PG::Connection.connect_start("dbname=mydatabase")
414
+ * socket = conn.socket_io
415
+ * status = conn.connect_poll
416
+ * while(status != PG::PGRES_POLLING_OK) do
417
+ * # do some work while waiting for the connection to complete
418
+ * if(status == PG::PGRES_POLLING_READING)
419
+ * if(not select([socket], [], [], 10.0))
420
+ * raise "Asynchronous connection timed out!"
421
+ * end
422
+ * elsif(status == PG::PGRES_POLLING_WRITING)
423
+ * if(not select([], [socket], [], 10.0))
424
+ * raise "Asynchronous connection timed out!"
425
+ * end
426
+ * end
427
+ * status = conn.connect_poll
428
+ * end
429
+ * # now conn.status == CONNECTION_OK, and connection
430
+ * # is ready.
431
+ */
432
+ static VALUE
433
+ pgconn_connect_poll(VALUE self)
434
+ {
435
+ PostgresPollingStatusType status;
436
+ status = PQconnectPoll(pg_get_pgconn(self));
437
+ return INT2FIX((int)status);
438
+ }
439
+
440
+ /*
441
+ * call-seq:
442
+ * conn.finish
443
+ *
444
+ * Closes the backend connection.
445
+ */
446
+ static VALUE
447
+ pgconn_finish( VALUE self )
448
+ {
449
+ pgconn_close_socket_io( self );
450
+ PQfinish( pg_get_pgconn(self) );
451
+ DATA_PTR( self ) = NULL;
452
+ return Qnil;
453
+ }
454
+
455
+
456
+ /*
457
+ * call-seq:
458
+ * conn.finished? -> boolean
459
+ *
460
+ * Returns +true+ if the backend connection has been closed.
461
+ */
462
+ static VALUE
463
+ pgconn_finished_p( VALUE self )
464
+ {
465
+ if ( DATA_PTR(self) ) return Qfalse;
466
+ return Qtrue;
467
+ }
468
+
469
+
470
+ /*
471
+ * call-seq:
472
+ * conn.reset()
473
+ *
474
+ * Resets the backend connection. This method closes the
475
+ * backend connection and tries to re-connect.
476
+ */
477
+ static VALUE
478
+ pgconn_reset( VALUE self )
479
+ {
480
+ pgconn_close_socket_io( self );
481
+ PQreset( pg_get_pgconn(self) );
482
+ return self;
483
+ }
484
+
485
+ /*
486
+ * call-seq:
487
+ * conn.reset_start() -> nil
488
+ *
489
+ * Initiate a connection reset in a nonblocking manner.
490
+ * This will close the current connection and attempt to
491
+ * reconnect using the same connection parameters.
492
+ * Use #reset_poll to check the status of the
493
+ * connection reset.
494
+ */
495
+ static VALUE
496
+ pgconn_reset_start(VALUE self)
497
+ {
498
+ pgconn_close_socket_io( self );
499
+ if(PQresetStart(pg_get_pgconn(self)) == 0)
500
+ rb_raise(rb_ePGerror, "reset has failed");
501
+ return Qnil;
502
+ }
503
+
504
+ /*
505
+ * call-seq:
506
+ * conn.reset_poll -> Fixnum
507
+ *
508
+ * Checks the status of a connection reset operation.
509
+ * See #connect_start and #connect_poll for
510
+ * usage information and return values.
511
+ */
512
+ static VALUE
513
+ pgconn_reset_poll(VALUE self)
514
+ {
515
+ PostgresPollingStatusType status;
516
+ status = PQresetPoll(pg_get_pgconn(self));
517
+ return INT2FIX((int)status);
518
+ }
519
+
520
+ /*
521
+ * call-seq:
522
+ * conn.db()
523
+ *
524
+ * Returns the connected database name.
525
+ */
526
+ static VALUE
527
+ pgconn_db(VALUE self)
528
+ {
529
+ char *db = PQdb(pg_get_pgconn(self));
530
+ if (!db) return Qnil;
531
+ return rb_tainted_str_new2(db);
532
+ }
533
+
534
+ /*
535
+ * call-seq:
536
+ * conn.user()
537
+ *
538
+ * Returns the authenticated user name.
539
+ */
540
+ static VALUE
541
+ pgconn_user(VALUE self)
542
+ {
543
+ char *user = PQuser(pg_get_pgconn(self));
544
+ if (!user) return Qnil;
545
+ return rb_tainted_str_new2(user);
546
+ }
547
+
548
+ /*
549
+ * call-seq:
550
+ * conn.pass()
551
+ *
552
+ * Returns the authenticated user name.
553
+ */
554
+ static VALUE
555
+ pgconn_pass(VALUE self)
556
+ {
557
+ char *user = PQpass(pg_get_pgconn(self));
558
+ if (!user) return Qnil;
559
+ return rb_tainted_str_new2(user);
560
+ }
561
+
562
+ /*
563
+ * call-seq:
564
+ * conn.host()
565
+ *
566
+ * Returns the connected server name.
567
+ */
568
+ static VALUE
569
+ pgconn_host(VALUE self)
570
+ {
571
+ char *host = PQhost(pg_get_pgconn(self));
572
+ if (!host) return Qnil;
573
+ return rb_tainted_str_new2(host);
574
+ }
575
+
576
+ /*
577
+ * call-seq:
578
+ * conn.port()
579
+ *
580
+ * Returns the connected server port number.
581
+ */
582
+ static VALUE
583
+ pgconn_port(VALUE self)
584
+ {
585
+ char* port = PQport(pg_get_pgconn(self));
586
+ return INT2NUM(atol(port));
587
+ }
588
+
589
+ /*
590
+ * call-seq:
591
+ * conn.tty()
592
+ *
593
+ * Returns the connected pgtty. (Obsolete)
594
+ */
595
+ static VALUE
596
+ pgconn_tty(VALUE self)
597
+ {
598
+ char *tty = PQtty(pg_get_pgconn(self));
599
+ if (!tty) return Qnil;
600
+ return rb_tainted_str_new2(tty);
601
+ }
602
+
603
+ /*
604
+ * call-seq:
605
+ * conn.options()
606
+ *
607
+ * Returns backend option string.
608
+ */
609
+ static VALUE
610
+ pgconn_options(VALUE self)
611
+ {
612
+ char *options = PQoptions(pg_get_pgconn(self));
613
+ if (!options) return Qnil;
614
+ return rb_tainted_str_new2(options);
615
+ }
616
+
617
+ /*
618
+ * call-seq:
619
+ * conn.status()
620
+ *
621
+ * Returns status of connection : CONNECTION_OK or CONNECTION_BAD
622
+ */
623
+ static VALUE
624
+ pgconn_status(VALUE self)
625
+ {
626
+ return INT2NUM(PQstatus(pg_get_pgconn(self)));
627
+ }
628
+
629
+ /*
630
+ * call-seq:
631
+ * conn.transaction_status()
632
+ *
633
+ * returns one of the following statuses:
634
+ * PQTRANS_IDLE = 0 (connection idle)
635
+ * PQTRANS_ACTIVE = 1 (command in progress)
636
+ * PQTRANS_INTRANS = 2 (idle, within transaction block)
637
+ * PQTRANS_INERROR = 3 (idle, within failed transaction)
638
+ * PQTRANS_UNKNOWN = 4 (cannot determine status)
639
+ */
640
+ static VALUE
641
+ pgconn_transaction_status(VALUE self)
642
+ {
643
+ return INT2NUM(PQtransactionStatus(pg_get_pgconn(self)));
644
+ }
645
+
646
+ /*
647
+ * call-seq:
648
+ * conn.parameter_status( param_name ) -> String
649
+ *
650
+ * Returns the setting of parameter _param_name_, where
651
+ * _param_name_ is one of
652
+ * * +server_version+
653
+ * * +server_encoding+
654
+ * * +client_encoding+
655
+ * * +is_superuser+
656
+ * * +session_authorization+
657
+ * * +DateStyle+
658
+ * * +TimeZone+
659
+ * * +integer_datetimes+
660
+ * * +standard_conforming_strings+
661
+ *
662
+ * Returns nil if the value of the parameter is not known.
663
+ */
664
+ static VALUE
665
+ pgconn_parameter_status(VALUE self, VALUE param_name)
666
+ {
667
+ const char *ret = PQparameterStatus(pg_get_pgconn(self), StringValuePtr(param_name));
668
+ if(ret == NULL)
669
+ return Qnil;
670
+ else
671
+ return rb_tainted_str_new2(ret);
672
+ }
673
+
674
+ /*
675
+ * call-seq:
676
+ * conn.protocol_version -> Integer
677
+ *
678
+ * The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4
679
+ * or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is
680
+ * obsolete and not supported by libpq.)
681
+ */
682
+ static VALUE
683
+ pgconn_protocol_version(VALUE self)
684
+ {
685
+ return INT2NUM(PQprotocolVersion(pg_get_pgconn(self)));
686
+ }
687
+
688
+ /*
689
+ * call-seq:
690
+ * conn.server_version -> Integer
691
+ *
692
+ * The number is formed by converting the major, minor, and revision
693
+ * numbers into two-decimal-digit numbers and appending them together.
694
+ * For example, version 7.4.2 will be returned as 70402, and version
695
+ * 8.1 will be returned as 80100 (leading zeroes are not shown). Zero
696
+ * is returned if the connection is bad.
697
+ *
698
+ */
699
+ static VALUE
700
+ pgconn_server_version(VALUE self)
701
+ {
702
+ return INT2NUM(PQserverVersion(pg_get_pgconn(self)));
703
+ }
704
+
705
+ /*
706
+ * call-seq:
707
+ * conn.error_message -> String
708
+ *
709
+ * Returns the error message about connection.
710
+ */
711
+ static VALUE
712
+ pgconn_error_message(VALUE self)
713
+ {
714
+ char *error = PQerrorMessage(pg_get_pgconn(self));
715
+ if (!error) return Qnil;
716
+ return rb_tainted_str_new2(error);
717
+ }
718
+
719
+ /*
720
+ * call-seq:
721
+ * conn.socket() -> Fixnum
722
+ *
723
+ * Returns the socket's file descriptor for this connection.
724
+ * <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
725
+ * If you do so, you will likely also want to set <tt>autoclose=false</tt>
726
+ * on it to prevent Ruby from closing the socket to PostgreSQL if it
727
+ * goes out of scope. Alternatively, you can use #socket_io, which
728
+ * creates an IO that's associated with the connection object itself,
729
+ * and so won't go out of scope until the connection does.
730
+ *
731
+ * *Note:* On Windows the file descriptor is not really usable,
732
+ * since it can not be used to build a Ruby IO object.
733
+ */
734
+ static VALUE
735
+ pgconn_socket(VALUE self)
736
+ {
737
+ int sd;
738
+ if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
739
+ rb_raise(rb_ePGerror, "Can't get socket descriptor");
740
+ return INT2NUM(sd);
741
+ }
742
+
743
+
744
+ #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
745
+
746
+ /*
747
+ * call-seq:
748
+ * conn.socket_io() -> IO
749
+ *
750
+ * Fetch a memoized IO object created from the Connection's underlying socket.
751
+ * This object can be used for IO.select to wait for events while running
752
+ * asynchronous API calls.
753
+ *
754
+ * Using this instead of #socket avoids the problem of the underlying connection
755
+ * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
756
+ * goes out of scope.
757
+ *
758
+ * This method can also be used on Windows but requires Ruby-2.0+.
759
+ */
760
+ static VALUE
761
+ pgconn_socket_io(VALUE self)
762
+ {
763
+ int sd;
764
+ int ruby_sd;
765
+ int id_autoclose = rb_intern("autoclose=");
766
+ VALUE socket_io = rb_iv_get( self, "@socket_io" );
767
+
768
+ if ( !RTEST(socket_io) ) {
769
+ if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
770
+ rb_raise(rb_ePGerror, "Can't get socket descriptor");
771
+
772
+ #ifdef _WIN32
773
+ ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
774
+ #else
775
+ ruby_sd = sd;
776
+ #endif
777
+
778
+ socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
779
+
780
+ /* Disable autoclose feature, when supported */
781
+ if( rb_respond_to(socket_io, id_autoclose) ){
782
+ rb_funcall( socket_io, id_autoclose, 1, Qfalse );
783
+ }
784
+
785
+ rb_iv_set( self, "@socket_io", socket_io );
786
+ }
787
+
788
+ return socket_io;
789
+ }
790
+
791
+ #endif
792
+
793
+ /*
794
+ * call-seq:
795
+ * conn.backend_pid() -> Fixnum
796
+ *
797
+ * Returns the process ID of the backend server
798
+ * process for this connection.
799
+ * Note that this is a PID on database server host.
800
+ */
801
+ static VALUE
802
+ pgconn_backend_pid(VALUE self)
803
+ {
804
+ return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
805
+ }
806
+
807
+ /*
808
+ * call-seq:
809
+ * conn.connection_needs_password() -> Boolean
810
+ *
811
+ * Returns +true+ if the authentication method required a
812
+ * password, but none was available. +false+ otherwise.
813
+ */
814
+ static VALUE
815
+ pgconn_connection_needs_password(VALUE self)
816
+ {
817
+ return PQconnectionNeedsPassword(pg_get_pgconn(self)) ? Qtrue : Qfalse;
818
+ }
819
+
820
+ /*
821
+ * call-seq:
822
+ * conn.connection_used_password() -> Boolean
823
+ *
824
+ * Returns +true+ if the authentication method used
825
+ * a caller-supplied password, +false+ otherwise.
826
+ */
827
+ static VALUE
828
+ pgconn_connection_used_password(VALUE self)
829
+ {
830
+ return PQconnectionUsedPassword(pg_get_pgconn(self)) ? Qtrue : Qfalse;
831
+ }
832
+
833
+
834
+ /* :TODO: get_ssl */
835
+
836
+
837
+ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
838
+
839
+ /*
840
+ * call-seq:
841
+ * conn.exec(sql) -> PG::Result
842
+ * conn.exec(sql) {|pg_result| block }
843
+ *
844
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
845
+ * Returns a PG::Result instance on success.
846
+ * On failure, it raises a PG::Error.
847
+ *
848
+ * For backward compatibility, if you pass more than one parameter to this method,
849
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
850
+ * argument placeholders are used.
851
+ *
852
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
853
+ * and the PG::Result object will automatically be cleared when the block terminates.
854
+ * In this instance, <code>conn.exec</code> returns the value of the block.
855
+ */
856
+ static VALUE
857
+ pgconn_exec(int argc, VALUE *argv, VALUE self)
858
+ {
859
+ PGconn *conn = pg_get_pgconn(self);
860
+ PGresult *result = NULL;
861
+ VALUE rb_pgresult;
862
+
863
+ /* If called with no parameters, use PQexec */
864
+ if ( argc == 1 ) {
865
+ Check_Type(argv[0], T_STRING);
866
+
867
+ result = gvl_PQexec(conn, StringValuePtr(argv[0]));
868
+ rb_pgresult = pg_new_result(result, self);
869
+ pg_result_check(rb_pgresult);
870
+ if (rb_block_given_p()) {
871
+ return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
872
+ }
873
+ return rb_pgresult;
874
+ }
875
+
876
+ /* Otherwise, just call #exec_params instead for backward-compatibility */
877
+ else {
878
+ return pgconn_exec_params( argc, argv, self );
879
+ }
880
+
881
+ }
882
+
883
+
884
+ /*
885
+ * call-seq:
886
+ * conn.exec_params(sql, params[, result_format ] ) -> PG::Result
887
+ * conn.exec_params(sql, params[, result_format ] ) {|pg_result| block }
888
+ *
889
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
890
+ * for parameters.
891
+ *
892
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
893
+ *
894
+ * +params+ is an array of the bind parameters for the SQL query.
895
+ * Each element of the +params+ array may be either:
896
+ * a hash of the form:
897
+ * {:value => String (value of bind parameter)
898
+ * :type => Fixnum (oid of type of bind parameter)
899
+ * :format => Fixnum (0 for text, 1 for binary)
900
+ * }
901
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
902
+ * { :value => <string value>, :type => 0, :format => 0 }
903
+ *
904
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
905
+ * inside the SQL query. The 0th element of the +params+ array is bound
906
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
907
+ *
908
+ * If the types are not specified, they will be inferred by PostgreSQL.
909
+ * Instead of specifying type oids, it's recommended to simply add
910
+ * explicit casts in the query to ensure that the right type is used.
911
+ *
912
+ * For example: "SELECT $1::int"
913
+ *
914
+ * The optional +result_format+ should be 0 for text results, 1
915
+ * for binary.
916
+ *
917
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
918
+ * and the PG::Result object will automatically be cleared when the block terminates.
919
+ * In this instance, <code>conn.exec</code> returns the value of the block.
920
+ */
921
+ static VALUE
922
+ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
923
+ {
924
+ PGconn *conn = pg_get_pgconn(self);
925
+ PGresult *result = NULL;
926
+ VALUE rb_pgresult;
927
+ VALUE command, params, in_res_fmt;
928
+ VALUE param, param_type, param_value, param_format;
929
+ VALUE param_value_tmp;
930
+ VALUE sym_type, sym_value, sym_format;
931
+ VALUE gc_array;
932
+ int i=0;
933
+ int nParams;
934
+ Oid *paramTypes;
935
+ char ** paramValues;
936
+ int *paramLengths;
937
+ int *paramFormats;
938
+ int resultFormat;
939
+
940
+ rb_scan_args(argc, argv, "12", &command, &params, &in_res_fmt);
941
+
942
+ /*
943
+ * Handle the edge-case where the caller is coming from #exec, but passed an explict +nil+
944
+ * for the second parameter.
945
+ */
946
+ if ( NIL_P(params) ) {
947
+ return pgconn_exec( 1, argv, self );
948
+ }
949
+
950
+ Check_Type(params, T_ARRAY);
951
+
952
+ if ( NIL_P(in_res_fmt) ) {
953
+ resultFormat = 0;
954
+ }
955
+ else {
956
+ resultFormat = NUM2INT(in_res_fmt);
957
+ }
958
+
959
+ gc_array = rb_ary_new();
960
+ rb_gc_register_address(&gc_array);
961
+
962
+ sym_type = ID2SYM(rb_intern("type"));
963
+ sym_value = ID2SYM(rb_intern("value"));
964
+ sym_format = ID2SYM(rb_intern("format"));
965
+ nParams = (int)RARRAY_LEN(params);
966
+ paramTypes = ALLOC_N(Oid, nParams);
967
+ paramValues = ALLOC_N(char *, nParams);
968
+ paramLengths = ALLOC_N(int, nParams);
969
+ paramFormats = ALLOC_N(int, nParams);
970
+
971
+ for ( i = 0; i < nParams; i++ ) {
972
+ param = rb_ary_entry(params, i);
973
+ if (TYPE(param) == T_HASH) {
974
+ param_type = rb_hash_aref(param, sym_type);
975
+ param_value_tmp = rb_hash_aref(param, sym_value);
976
+ if(param_value_tmp == Qnil)
977
+ param_value = param_value_tmp;
978
+ else
979
+ param_value = rb_obj_as_string(param_value_tmp);
980
+ param_format = rb_hash_aref(param, sym_format);
981
+ }
982
+ else {
983
+ param_type = Qnil;
984
+ if(param == Qnil)
985
+ param_value = param;
986
+ else
987
+ param_value = rb_obj_as_string(param);
988
+ param_format = Qnil;
989
+ }
990
+
991
+ if(param_type == Qnil)
992
+ paramTypes[i] = 0;
993
+ else
994
+ paramTypes[i] = NUM2INT(param_type);
995
+
996
+ if(param_value == Qnil) {
997
+ paramValues[i] = NULL;
998
+ paramLengths[i] = 0;
999
+ }
1000
+ else {
1001
+ Check_Type(param_value, T_STRING);
1002
+ /* make sure param_value doesn't get freed by the GC */
1003
+ rb_ary_push(gc_array, param_value);
1004
+ paramValues[i] = StringValuePtr(param_value);
1005
+ paramLengths[i] = (int)RSTRING_LEN(param_value);
1006
+ }
1007
+
1008
+ if(param_format == Qnil)
1009
+ paramFormats[i] = 0;
1010
+ else
1011
+ paramFormats[i] = NUM2INT(param_format);
1012
+ }
1013
+
1014
+ result = gvl_PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
1015
+ (const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
1016
+
1017
+ rb_gc_unregister_address(&gc_array);
1018
+
1019
+ xfree(paramTypes);
1020
+ xfree(paramValues);
1021
+ xfree(paramLengths);
1022
+ xfree(paramFormats);
1023
+
1024
+ rb_pgresult = pg_new_result(result, self);
1025
+ pg_result_check(rb_pgresult);
1026
+
1027
+ if (rb_block_given_p()) {
1028
+ return rb_ensure(rb_yield, rb_pgresult, pg_result_clear, rb_pgresult);
1029
+ }
1030
+
1031
+ return rb_pgresult;
1032
+ }
1033
+
1034
+ /*
1035
+ * call-seq:
1036
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1037
+ *
1038
+ * Prepares statement _sql_ with name _name_ to be executed later.
1039
+ * Returns a PG::Result instance on success.
1040
+ * On failure, it raises a PG::Error.
1041
+ *
1042
+ * +param_types+ is an optional parameter to specify the Oids of the
1043
+ * types of the parameters.
1044
+ *
1045
+ * If the types are not specified, they will be inferred by PostgreSQL.
1046
+ * Instead of specifying type oids, it's recommended to simply add
1047
+ * explicit casts in the query to ensure that the right type is used.
1048
+ *
1049
+ * For example: "SELECT $1::int"
1050
+ *
1051
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1052
+ * inside the SQL query.
1053
+ */
1054
+ static VALUE
1055
+ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1056
+ {
1057
+ PGconn *conn = pg_get_pgconn(self);
1058
+ PGresult *result = NULL;
1059
+ VALUE rb_pgresult;
1060
+ VALUE name, command, in_paramtypes;
1061
+ VALUE param;
1062
+ int i = 0;
1063
+ int nParams = 0;
1064
+ Oid *paramTypes = NULL;
1065
+
1066
+ rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1067
+ Check_Type(name, T_STRING);
1068
+ Check_Type(command, T_STRING);
1069
+
1070
+ if(! NIL_P(in_paramtypes)) {
1071
+ Check_Type(in_paramtypes, T_ARRAY);
1072
+ nParams = (int)RARRAY_LEN(in_paramtypes);
1073
+ paramTypes = ALLOC_N(Oid, nParams);
1074
+ for(i = 0; i < nParams; i++) {
1075
+ param = rb_ary_entry(in_paramtypes, i);
1076
+ Check_Type(param, T_FIXNUM);
1077
+ if(param == Qnil)
1078
+ paramTypes[i] = 0;
1079
+ else
1080
+ paramTypes[i] = NUM2INT(param);
1081
+ }
1082
+ }
1083
+ result = gvl_PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
1084
+ nParams, paramTypes);
1085
+
1086
+ xfree(paramTypes);
1087
+
1088
+ rb_pgresult = pg_new_result(result, self);
1089
+ pg_result_check(rb_pgresult);
1090
+ return rb_pgresult;
1091
+ }
1092
+
1093
+ /*
1094
+ * call-seq:
1095
+ * conn.exec_prepared(statement_name [, params, result_format ] ) -> PG::Result
1096
+ * conn.exec_prepared(statement_name [, params, result_format ] ) {|pg_result| block }
1097
+ *
1098
+ * Execute prepared named statement specified by _statement_name_.
1099
+ * Returns a PG::Result instance on success.
1100
+ * On failure, it raises a PG::Error.
1101
+ *
1102
+ * +params+ is an array of the optional bind parameters for the
1103
+ * SQL query. Each element of the +params+ array may be either:
1104
+ * a hash of the form:
1105
+ * {:value => String (value of bind parameter)
1106
+ * :format => Fixnum (0 for text, 1 for binary)
1107
+ * }
1108
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
1109
+ * { :value => <string value>, :format => 0 }
1110
+ *
1111
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1112
+ * inside the SQL query. The 0th element of the +params+ array is bound
1113
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1114
+ *
1115
+ * The optional +result_format+ should be 0 for text results, 1
1116
+ * for binary.
1117
+ *
1118
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
1119
+ * and the PG::Result object will automatically be cleared when the block terminates.
1120
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1121
+ */
1122
+ static VALUE
1123
+ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1124
+ {
1125
+ PGconn *conn = pg_get_pgconn(self);
1126
+ PGresult *result = NULL;
1127
+ VALUE rb_pgresult;
1128
+ VALUE name, params, in_res_fmt;
1129
+ VALUE param, param_value, param_format;
1130
+ VALUE param_value_tmp;
1131
+ VALUE sym_value, sym_format;
1132
+ VALUE gc_array;
1133
+ int i = 0;
1134
+ int nParams;
1135
+ char ** paramValues;
1136
+ int *paramLengths;
1137
+ int *paramFormats;
1138
+ int resultFormat;
1139
+
1140
+
1141
+ rb_scan_args(argc, argv, "12", &name, &params, &in_res_fmt);
1142
+ Check_Type(name, T_STRING);
1143
+
1144
+ if(NIL_P(params)) {
1145
+ params = rb_ary_new2(0);
1146
+ resultFormat = 0;
1147
+ }
1148
+ else {
1149
+ Check_Type(params, T_ARRAY);
1150
+ }
1151
+
1152
+ if(NIL_P(in_res_fmt)) {
1153
+ resultFormat = 0;
1154
+ }
1155
+ else {
1156
+ resultFormat = NUM2INT(in_res_fmt);
1157
+ }
1158
+
1159
+ gc_array = rb_ary_new();
1160
+ rb_gc_register_address(&gc_array);
1161
+ sym_value = ID2SYM(rb_intern("value"));
1162
+ sym_format = ID2SYM(rb_intern("format"));
1163
+ nParams = (int)RARRAY_LEN(params);
1164
+ paramValues = ALLOC_N(char *, nParams);
1165
+ paramLengths = ALLOC_N(int, nParams);
1166
+ paramFormats = ALLOC_N(int, nParams);
1167
+ for(i = 0; i < nParams; i++) {
1168
+ param = rb_ary_entry(params, i);
1169
+ if (TYPE(param) == T_HASH) {
1170
+ param_value_tmp = rb_hash_aref(param, sym_value);
1171
+ if(param_value_tmp == Qnil)
1172
+ param_value = param_value_tmp;
1173
+ else
1174
+ param_value = rb_obj_as_string(param_value_tmp);
1175
+ param_format = rb_hash_aref(param, sym_format);
1176
+ }
1177
+ else {
1178
+ if(param == Qnil)
1179
+ param_value = param;
1180
+ else
1181
+ param_value = rb_obj_as_string(param);
1182
+ param_format = INT2NUM(0);
1183
+ }
1184
+ if(param_value == Qnil) {
1185
+ paramValues[i] = NULL;
1186
+ paramLengths[i] = 0;
1187
+ }
1188
+ else {
1189
+ Check_Type(param_value, T_STRING);
1190
+ /* make sure param_value doesn't get freed by the GC */
1191
+ rb_ary_push(gc_array, param_value);
1192
+ paramValues[i] = StringValuePtr(param_value);
1193
+ paramLengths[i] = (int)RSTRING_LEN(param_value);
1194
+ }
1195
+
1196
+ if(param_format == Qnil)
1197
+ paramFormats[i] = 0;
1198
+ else
1199
+ paramFormats[i] = NUM2INT(param_format);
1200
+ }
1201
+
1202
+ result = gvl_PQexecPrepared(conn, StringValuePtr(name), nParams,
1203
+ (const char * const *)paramValues, paramLengths, paramFormats,
1204
+ resultFormat);
1205
+
1206
+ rb_gc_unregister_address(&gc_array);
1207
+
1208
+ xfree(paramValues);
1209
+ xfree(paramLengths);
1210
+ xfree(paramFormats);
1211
+
1212
+ rb_pgresult = pg_new_result(result, self);
1213
+ pg_result_check(rb_pgresult);
1214
+ if (rb_block_given_p()) {
1215
+ return rb_ensure(rb_yield, rb_pgresult,
1216
+ pg_result_clear, rb_pgresult);
1217
+ }
1218
+ return rb_pgresult;
1219
+ }
1220
+
1221
+ /*
1222
+ * call-seq:
1223
+ * conn.describe_prepared( statement_name ) -> PG::Result
1224
+ *
1225
+ * Retrieve information about the prepared statement
1226
+ * _statement_name_.
1227
+ */
1228
+ static VALUE
1229
+ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1230
+ {
1231
+ PGresult *result;
1232
+ VALUE rb_pgresult;
1233
+ PGconn *conn = pg_get_pgconn(self);
1234
+ char *stmt;
1235
+ if(stmt_name == Qnil) {
1236
+ stmt = NULL;
1237
+ }
1238
+ else {
1239
+ Check_Type(stmt_name, T_STRING);
1240
+ stmt = StringValuePtr(stmt_name);
1241
+ }
1242
+ result = gvl_PQdescribePrepared(conn, stmt);
1243
+ rb_pgresult = pg_new_result(result, self);
1244
+ pg_result_check(rb_pgresult);
1245
+ return rb_pgresult;
1246
+ }
1247
+
1248
+
1249
+ /*
1250
+ * call-seq:
1251
+ * conn.describe_portal( portal_name ) -> PG::Result
1252
+ *
1253
+ * Retrieve information about the portal _portal_name_.
1254
+ */
1255
+ static VALUE
1256
+ pgconn_describe_portal(self, stmt_name)
1257
+ VALUE self, stmt_name;
1258
+ {
1259
+ PGresult *result;
1260
+ VALUE rb_pgresult;
1261
+ PGconn *conn = pg_get_pgconn(self);
1262
+ char *stmt;
1263
+ if(stmt_name == Qnil) {
1264
+ stmt = NULL;
1265
+ }
1266
+ else {
1267
+ Check_Type(stmt_name, T_STRING);
1268
+ stmt = StringValuePtr(stmt_name);
1269
+ }
1270
+ result = gvl_PQdescribePortal(conn, stmt);
1271
+ rb_pgresult = pg_new_result(result, self);
1272
+ pg_result_check(rb_pgresult);
1273
+ return rb_pgresult;
1274
+ }
1275
+
1276
+
1277
+ /*
1278
+ * call-seq:
1279
+ * conn.make_empty_pgresult( status ) -> PG::Result
1280
+ *
1281
+ * Constructs and empty PG::Result with status _status_.
1282
+ * _status_ may be one of:
1283
+ * * +PGRES_EMPTY_QUERY+
1284
+ * * +PGRES_COMMAND_OK+
1285
+ * * +PGRES_TUPLES_OK+
1286
+ * * +PGRES_COPY_OUT+
1287
+ * * +PGRES_COPY_IN+
1288
+ * * +PGRES_BAD_RESPONSE+
1289
+ * * +PGRES_NONFATAL_ERROR+
1290
+ * * +PGRES_FATAL_ERROR+
1291
+ * * +PGRES_COPY_BOTH+
1292
+ */
1293
+ static VALUE
1294
+ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1295
+ {
1296
+ PGresult *result;
1297
+ VALUE rb_pgresult;
1298
+ PGconn *conn = pg_get_pgconn(self);
1299
+ result = PQmakeEmptyPGresult(conn, NUM2INT(status));
1300
+ rb_pgresult = pg_new_result(result, self);
1301
+ pg_result_check(rb_pgresult);
1302
+ return rb_pgresult;
1303
+ }
1304
+
1305
+
1306
+ /*
1307
+ * call-seq:
1308
+ * conn.escape_string( str ) -> String
1309
+ *
1310
+ * Connection instance method for versions of 8.1 and higher of libpq
1311
+ * uses PQescapeStringConn, which is safer. Avoid calling as a class method,
1312
+ * the class method uses the deprecated PQescapeString() API function.
1313
+ *
1314
+ * Returns a SQL-safe version of the String _str_.
1315
+ * This is the preferred way to make strings safe for inclusion in
1316
+ * SQL queries.
1317
+ *
1318
+ * Consider using exec_params, which avoids the need for passing values
1319
+ * inside of SQL commands.
1320
+ *
1321
+ * Encoding of escaped string will be equal to client encoding of connection.
1322
+ */
1323
+ static VALUE
1324
+ pgconn_s_escape(VALUE self, VALUE string)
1325
+ {
1326
+ char *escaped;
1327
+ size_t size;
1328
+ int error;
1329
+ VALUE result;
1330
+ #ifdef M17N_SUPPORTED
1331
+ rb_encoding* enc;
1332
+ #endif
1333
+
1334
+ Check_Type(string, T_STRING);
1335
+
1336
+ escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
1337
+ if(rb_obj_class(self) == rb_cPGconn) {
1338
+ size = PQescapeStringConn(pg_get_pgconn(self), escaped,
1339
+ RSTRING_PTR(string), RSTRING_LEN(string), &error);
1340
+ if(error) {
1341
+ xfree(escaped);
1342
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1343
+ }
1344
+ } else {
1345
+ size = PQescapeString(escaped, RSTRING_PTR(string), (int)RSTRING_LEN(string));
1346
+ }
1347
+ result = rb_str_new(escaped, size);
1348
+ xfree(escaped);
1349
+ OBJ_INFECT(result, string);
1350
+
1351
+ #ifdef M17N_SUPPORTED
1352
+ if ( rb_obj_class(self) == rb_cPGconn ) {
1353
+ enc = pg_conn_enc_get( pg_get_pgconn(self) );
1354
+ } else {
1355
+ enc = rb_enc_get(string);
1356
+ }
1357
+ rb_enc_associate(result, enc);
1358
+ #endif
1359
+
1360
+ return result;
1361
+ }
1362
+
1363
+ /*
1364
+ * call-seq:
1365
+ * conn.escape_bytea( string ) -> String
1366
+ *
1367
+ * Connection instance method for versions of 8.1 and higher of libpq
1368
+ * uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
1369
+ * the class method uses the deprecated PQescapeBytea() API function.
1370
+ *
1371
+ * Use the instance method version of this function, it is safer than the
1372
+ * class method.
1373
+ *
1374
+ * Escapes binary data for use within an SQL command with the type +bytea+.
1375
+ *
1376
+ * Certain byte values must be escaped (but all byte values may be escaped)
1377
+ * when used as part of a +bytea+ literal in an SQL statement. In general, to
1378
+ * escape a byte, it is converted into the three digit octal number equal to
1379
+ * the octet value, and preceded by two backslashes. The single quote (') and
1380
+ * backslash (\) characters have special alternative escape sequences.
1381
+ * #escape_bytea performs this operation, escaping only the minimally required
1382
+ * bytes.
1383
+ *
1384
+ * Consider using exec_params, which avoids the need for passing values inside of
1385
+ * SQL commands.
1386
+ */
1387
+ static VALUE
1388
+ pgconn_s_escape_bytea(VALUE self, VALUE str)
1389
+ {
1390
+ unsigned char *from, *to;
1391
+ size_t from_len, to_len;
1392
+ VALUE ret;
1393
+
1394
+ Check_Type(str, T_STRING);
1395
+ from = (unsigned char*)RSTRING_PTR(str);
1396
+ from_len = RSTRING_LEN(str);
1397
+
1398
+ if(rb_obj_class(self) == rb_cPGconn) {
1399
+ to = PQescapeByteaConn(pg_get_pgconn(self), from, from_len, &to_len);
1400
+ } else {
1401
+ to = PQescapeBytea( from, from_len, &to_len);
1402
+ }
1403
+
1404
+ ret = rb_str_new((char*)to, to_len - 1);
1405
+ OBJ_INFECT(ret, str);
1406
+ PQfreemem(to);
1407
+ return ret;
1408
+ }
1409
+
1410
+
1411
+ /*
1412
+ * call-seq:
1413
+ * PG::Connection.unescape_bytea( string )
1414
+ *
1415
+ * Converts an escaped string representation of binary data into binary data --- the
1416
+ * reverse of #escape_bytea. This is needed when retrieving +bytea+ data in text format,
1417
+ * but not when retrieving it in binary format.
1418
+ *
1419
+ */
1420
+ static VALUE
1421
+ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1422
+ {
1423
+ unsigned char *from, *to;
1424
+ size_t to_len;
1425
+ VALUE ret;
1426
+
1427
+ UNUSED( self );
1428
+
1429
+ Check_Type(str, T_STRING);
1430
+ from = (unsigned char*)StringValuePtr(str);
1431
+
1432
+ to = PQunescapeBytea(from, &to_len);
1433
+
1434
+ ret = rb_str_new((char*)to, to_len);
1435
+ OBJ_INFECT(ret, str);
1436
+ PQfreemem(to);
1437
+ return ret;
1438
+ }
1439
+
1440
+ #ifdef HAVE_PQESCAPELITERAL
1441
+ /*
1442
+ * call-seq:
1443
+ * conn.escape_literal( str ) -> String
1444
+ *
1445
+ * Escape an arbitrary String +str+ as a literal.
1446
+ */
1447
+ static VALUE
1448
+ pgconn_escape_literal(VALUE self, VALUE string)
1449
+ {
1450
+ PGconn *conn = pg_get_pgconn(self);
1451
+ char *escaped = NULL;
1452
+ VALUE error;
1453
+ VALUE result = Qnil;
1454
+
1455
+ Check_Type(string, T_STRING);
1456
+
1457
+ escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1458
+ if (escaped == NULL)
1459
+ {
1460
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1461
+ rb_iv_set(error, "@connection", self);
1462
+ rb_exc_raise(error);
1463
+ return Qnil;
1464
+ }
1465
+ result = rb_str_new2(escaped);
1466
+ PQfreemem(escaped);
1467
+ OBJ_INFECT(result, string);
1468
+
1469
+ return result;
1470
+ }
1471
+ #endif
1472
+
1473
+ #ifdef HAVE_PQESCAPEIDENTIFIER
1474
+ /*
1475
+ * call-seq:
1476
+ * conn.escape_identifier( str ) -> String
1477
+ *
1478
+ * Escape an arbitrary String +str+ as an identifier.
1479
+ */
1480
+ static VALUE
1481
+ pgconn_escape_identifier(VALUE self, VALUE string)
1482
+ {
1483
+ PGconn *conn = pg_get_pgconn(self);
1484
+ char *escaped = NULL;
1485
+ VALUE error;
1486
+ VALUE result = Qnil;
1487
+
1488
+ Check_Type(string, T_STRING);
1489
+
1490
+ escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1491
+ if (escaped == NULL)
1492
+ {
1493
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1494
+ rb_iv_set(error, "@connection", self);
1495
+ rb_exc_raise(error);
1496
+ return Qnil;
1497
+ }
1498
+ result = rb_str_new2(escaped);
1499
+ PQfreemem(escaped);
1500
+ OBJ_INFECT(result, string);
1501
+
1502
+ return result;
1503
+ }
1504
+ #endif
1505
+
1506
+ #ifdef HAVE_PQSETSINGLEROWMODE
1507
+ /*
1508
+ * call-seq:
1509
+ * conn.set_single_row_mode -> self
1510
+ *
1511
+ * To enter single-row mode, call this method immediately after a successful
1512
+ * call of send_query (or a sibling function). This mode selection is effective
1513
+ * only for the currently executing query.
1514
+ * Then call Connection#get_result repeatedly, until it returns nil.
1515
+ *
1516
+ * Each (but the last) received Result has exactly one row and a
1517
+ * Result#result_status of PGRES_SINGLE_TUPLE. The last row has
1518
+ * zero rows and is used to indicate a successful execution of the query.
1519
+ * All of these Result objects will contain the same row description data
1520
+ * (column names, types, etc) that an ordinary Result object for the query
1521
+ * would have.
1522
+ *
1523
+ * *Caution:* While processing a query, the server may return some rows and
1524
+ * then encounter an error, causing the query to be aborted. Ordinarily, pg
1525
+ * discards any such rows and reports only the error. But in single-row mode,
1526
+ * those rows will have already been returned to the application. Hence, the
1527
+ * application will see some Result objects followed by an Error raised in get_result.
1528
+ * For proper transactional behavior, the application must be designed to discard
1529
+ * or undo whatever has been done with the previously-processed rows, if the query
1530
+ * ultimately fails.
1531
+ *
1532
+ * Example:
1533
+ * conn.send_query( "your SQL command" )
1534
+ * conn.set_single_row_mode
1535
+ * loop do
1536
+ * res = conn.get_result or break
1537
+ * res.check
1538
+ * res.each do |row|
1539
+ * # do something with the received row
1540
+ * end
1541
+ * end
1542
+ *
1543
+ */
1544
+ static VALUE
1545
+ pgconn_set_single_row_mode(VALUE self)
1546
+ {
1547
+ PGconn *conn = pg_get_pgconn(self);
1548
+ VALUE error;
1549
+
1550
+ if( PQsetSingleRowMode(conn) == 0 )
1551
+ {
1552
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1553
+ rb_iv_set(error, "@connection", self);
1554
+ rb_exc_raise(error);
1555
+ }
1556
+
1557
+ return self;
1558
+ }
1559
+ #endif
1560
+
1561
+ /*
1562
+ * call-seq:
1563
+ * conn.send_query(sql [, params, result_format ] ) -> nil
1564
+ *
1565
+ * Sends SQL query request specified by _sql_ to PostgreSQL for
1566
+ * asynchronous processing, and immediately returns.
1567
+ * On failure, it raises a PG::Error.
1568
+ *
1569
+ * +params+ is an optional array of the bind parameters for the SQL query.
1570
+ * Each element of the +params+ array may be either:
1571
+ * a hash of the form:
1572
+ * {:value => String (value of bind parameter)
1573
+ * :type => Fixnum (oid of type of bind parameter)
1574
+ * :format => Fixnum (0 for text, 1 for binary)
1575
+ * }
1576
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
1577
+ * { :value => <string value>, :type => 0, :format => 0 }
1578
+ *
1579
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1580
+ * inside the SQL query. The 0th element of the +params+ array is bound
1581
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1582
+ *
1583
+ * If the types are not specified, they will be inferred by PostgreSQL.
1584
+ * Instead of specifying type oids, it's recommended to simply add
1585
+ * explicit casts in the query to ensure that the right type is used.
1586
+ *
1587
+ * For example: "SELECT $1::int"
1588
+ *
1589
+ * The optional +result_format+ should be 0 for text results, 1
1590
+ * for binary.
1591
+ */
1592
+ static VALUE
1593
+ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1594
+ {
1595
+ PGconn *conn = pg_get_pgconn(self);
1596
+ int result;
1597
+ VALUE command, params, in_res_fmt;
1598
+ VALUE param, param_type, param_value, param_format;
1599
+ VALUE param_value_tmp;
1600
+ VALUE sym_type, sym_value, sym_format;
1601
+ VALUE gc_array;
1602
+ VALUE error;
1603
+ int i=0;
1604
+ int nParams;
1605
+ Oid *paramTypes;
1606
+ char ** paramValues;
1607
+ int *paramLengths;
1608
+ int *paramFormats;
1609
+ int resultFormat;
1610
+
1611
+ rb_scan_args(argc, argv, "12", &command, &params, &in_res_fmt);
1612
+ Check_Type(command, T_STRING);
1613
+
1614
+ /* If called with no parameters, use PQsendQuery */
1615
+ if(NIL_P(params)) {
1616
+ if(PQsendQuery(conn,StringValuePtr(command)) == 0) {
1617
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1618
+ rb_iv_set(error, "@connection", self);
1619
+ rb_exc_raise(error);
1620
+ }
1621
+ return Qnil;
1622
+ }
1623
+
1624
+ /* If called with parameters, and optionally result_format,
1625
+ * use PQsendQueryParams
1626
+ */
1627
+ Check_Type(params, T_ARRAY);
1628
+
1629
+ if(NIL_P(in_res_fmt)) {
1630
+ resultFormat = 0;
1631
+ }
1632
+ else {
1633
+ resultFormat = NUM2INT(in_res_fmt);
1634
+ }
1635
+
1636
+ gc_array = rb_ary_new();
1637
+ rb_gc_register_address(&gc_array);
1638
+ sym_type = ID2SYM(rb_intern("type"));
1639
+ sym_value = ID2SYM(rb_intern("value"));
1640
+ sym_format = ID2SYM(rb_intern("format"));
1641
+ nParams = (int)RARRAY_LEN(params);
1642
+ paramTypes = ALLOC_N(Oid, nParams);
1643
+ paramValues = ALLOC_N(char *, nParams);
1644
+ paramLengths = ALLOC_N(int, nParams);
1645
+ paramFormats = ALLOC_N(int, nParams);
1646
+ for(i = 0; i < nParams; i++) {
1647
+ param = rb_ary_entry(params, i);
1648
+ if (TYPE(param) == T_HASH) {
1649
+ param_type = rb_hash_aref(param, sym_type);
1650
+ param_value_tmp = rb_hash_aref(param, sym_value);
1651
+ if(param_value_tmp == Qnil)
1652
+ param_value = param_value_tmp;
1653
+ else
1654
+ param_value = rb_obj_as_string(param_value_tmp);
1655
+ param_format = rb_hash_aref(param, sym_format);
1656
+ }
1657
+ else {
1658
+ param_type = INT2NUM(0);
1659
+ if(param == Qnil)
1660
+ param_value = param;
1661
+ else
1662
+ param_value = rb_obj_as_string(param);
1663
+ param_format = INT2NUM(0);
1664
+ }
1665
+
1666
+ if(param_type == Qnil)
1667
+ paramTypes[i] = 0;
1668
+ else
1669
+ paramTypes[i] = NUM2INT(param_type);
1670
+
1671
+ if(param_value == Qnil) {
1672
+ paramValues[i] = NULL;
1673
+ paramLengths[i] = 0;
1674
+ }
1675
+ else {
1676
+ Check_Type(param_value, T_STRING);
1677
+ /* make sure param_value doesn't get freed by the GC */
1678
+ rb_ary_push(gc_array, param_value);
1679
+ paramValues[i] = StringValuePtr(param_value);
1680
+ paramLengths[i] = (int)RSTRING_LEN(param_value);
1681
+ }
1682
+
1683
+ if(param_format == Qnil)
1684
+ paramFormats[i] = 0;
1685
+ else
1686
+ paramFormats[i] = NUM2INT(param_format);
1687
+ }
1688
+
1689
+ result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
1690
+ (const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
1691
+
1692
+ rb_gc_unregister_address(&gc_array);
1693
+
1694
+ xfree(paramTypes);
1695
+ xfree(paramValues);
1696
+ xfree(paramLengths);
1697
+ xfree(paramFormats);
1698
+
1699
+ if(result == 0) {
1700
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1701
+ rb_iv_set(error, "@connection", self);
1702
+ rb_exc_raise(error);
1703
+ }
1704
+ return Qnil;
1705
+ }
1706
+
1707
+ /*
1708
+ * call-seq:
1709
+ * conn.send_prepare( stmt_name, sql [, param_types ] ) -> nil
1710
+ *
1711
+ * Prepares statement _sql_ with name _name_ to be executed later.
1712
+ * Sends prepare command asynchronously, and returns immediately.
1713
+ * On failure, it raises a PG::Error.
1714
+ *
1715
+ * +param_types+ is an optional parameter to specify the Oids of the
1716
+ * types of the parameters.
1717
+ *
1718
+ * If the types are not specified, they will be inferred by PostgreSQL.
1719
+ * Instead of specifying type oids, it's recommended to simply add
1720
+ * explicit casts in the query to ensure that the right type is used.
1721
+ *
1722
+ * For example: "SELECT $1::int"
1723
+ *
1724
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1725
+ * inside the SQL query.
1726
+ */
1727
+ static VALUE
1728
+ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1729
+ {
1730
+ PGconn *conn = pg_get_pgconn(self);
1731
+ int result;
1732
+ VALUE name, command, in_paramtypes;
1733
+ VALUE param;
1734
+ VALUE error;
1735
+ int i = 0;
1736
+ int nParams = 0;
1737
+ Oid *paramTypes = NULL;
1738
+
1739
+ rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1740
+ Check_Type(name, T_STRING);
1741
+ Check_Type(command, T_STRING);
1742
+
1743
+ if(! NIL_P(in_paramtypes)) {
1744
+ Check_Type(in_paramtypes, T_ARRAY);
1745
+ nParams = (int)RARRAY_LEN(in_paramtypes);
1746
+ paramTypes = ALLOC_N(Oid, nParams);
1747
+ for(i = 0; i < nParams; i++) {
1748
+ param = rb_ary_entry(in_paramtypes, i);
1749
+ Check_Type(param, T_FIXNUM);
1750
+ if(param == Qnil)
1751
+ paramTypes[i] = 0;
1752
+ else
1753
+ paramTypes[i] = NUM2INT(param);
1754
+ }
1755
+ }
1756
+ result = PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
1757
+ nParams, paramTypes);
1758
+
1759
+ xfree(paramTypes);
1760
+
1761
+ if(result == 0) {
1762
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1763
+ rb_iv_set(error, "@connection", self);
1764
+ rb_exc_raise(error);
1765
+ }
1766
+ return Qnil;
1767
+ }
1768
+
1769
+ /*
1770
+ * call-seq:
1771
+ * conn.send_query_prepared( statement_name [, params, result_format ] )
1772
+ * -> nil
1773
+ *
1774
+ * Execute prepared named statement specified by _statement_name_
1775
+ * asynchronously, and returns immediately.
1776
+ * On failure, it raises a PG::Error.
1777
+ *
1778
+ * +params+ is an array of the optional bind parameters for the
1779
+ * SQL query. Each element of the +params+ array may be either:
1780
+ * a hash of the form:
1781
+ * {:value => String (value of bind parameter)
1782
+ * :format => Fixnum (0 for text, 1 for binary)
1783
+ * }
1784
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
1785
+ * { :value => <string value>, :format => 0 }
1786
+ *
1787
+ * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1788
+ * inside the SQL query. The 0th element of the +params+ array is bound
1789
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1790
+ *
1791
+ * The optional +result_format+ should be 0 for text results, 1
1792
+ * for binary.
1793
+ */
1794
+ static VALUE
1795
+ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1796
+ {
1797
+ PGconn *conn = pg_get_pgconn(self);
1798
+ int result;
1799
+ VALUE name, params, in_res_fmt;
1800
+ VALUE param, param_value, param_format;
1801
+ VALUE param_value_tmp;
1802
+ VALUE sym_value, sym_format;
1803
+ VALUE gc_array;
1804
+ VALUE error;
1805
+ int i = 0;
1806
+ int nParams;
1807
+ char ** paramValues;
1808
+ int *paramLengths;
1809
+ int *paramFormats;
1810
+ int resultFormat;
1811
+
1812
+ rb_scan_args(argc, argv, "12", &name, &params, &in_res_fmt);
1813
+ Check_Type(name, T_STRING);
1814
+
1815
+ if(NIL_P(params)) {
1816
+ params = rb_ary_new2(0);
1817
+ resultFormat = 0;
1818
+ }
1819
+ else {
1820
+ Check_Type(params, T_ARRAY);
1821
+ }
1822
+
1823
+ if(NIL_P(in_res_fmt)) {
1824
+ resultFormat = 0;
1825
+ }
1826
+ else {
1827
+ resultFormat = NUM2INT(in_res_fmt);
1828
+ }
1829
+
1830
+ gc_array = rb_ary_new();
1831
+ rb_gc_register_address(&gc_array);
1832
+ sym_value = ID2SYM(rb_intern("value"));
1833
+ sym_format = ID2SYM(rb_intern("format"));
1834
+ nParams = (int)RARRAY_LEN(params);
1835
+ paramValues = ALLOC_N(char *, nParams);
1836
+ paramLengths = ALLOC_N(int, nParams);
1837
+ paramFormats = ALLOC_N(int, nParams);
1838
+ for(i = 0; i < nParams; i++) {
1839
+ param = rb_ary_entry(params, i);
1840
+ if (TYPE(param) == T_HASH) {
1841
+ param_value_tmp = rb_hash_aref(param, sym_value);
1842
+ if(param_value_tmp == Qnil)
1843
+ param_value = param_value_tmp;
1844
+ else
1845
+ param_value = rb_obj_as_string(param_value_tmp);
1846
+ param_format = rb_hash_aref(param, sym_format);
1847
+ }
1848
+ else {
1849
+ if(param == Qnil)
1850
+ param_value = param;
1851
+ else
1852
+ param_value = rb_obj_as_string(param);
1853
+ param_format = INT2NUM(0);
1854
+ }
1855
+
1856
+ if(param_value == Qnil) {
1857
+ paramValues[i] = NULL;
1858
+ paramLengths[i] = 0;
1859
+ }
1860
+ else {
1861
+ Check_Type(param_value, T_STRING);
1862
+ /* make sure param_value doesn't get freed by the GC */
1863
+ rb_ary_push(gc_array, param_value);
1864
+ paramValues[i] = StringValuePtr(param_value);
1865
+ paramLengths[i] = (int)RSTRING_LEN(param_value);
1866
+ }
1867
+
1868
+ if(param_format == Qnil)
1869
+ paramFormats[i] = 0;
1870
+ else
1871
+ paramFormats[i] = NUM2INT(param_format);
1872
+ }
1873
+
1874
+ result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
1875
+ (const char * const *)paramValues, paramLengths, paramFormats,
1876
+ resultFormat);
1877
+
1878
+ rb_gc_unregister_address(&gc_array);
1879
+
1880
+ xfree(paramValues);
1881
+ xfree(paramLengths);
1882
+ xfree(paramFormats);
1883
+
1884
+ if(result == 0) {
1885
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1886
+ rb_iv_set(error, "@connection", self);
1887
+ rb_exc_raise(error);
1888
+ }
1889
+ return Qnil;
1890
+ }
1891
+
1892
+ /*
1893
+ * call-seq:
1894
+ * conn.send_describe_prepared( statement_name ) -> nil
1895
+ *
1896
+ * Asynchronously send _command_ to the server. Does not block.
1897
+ * Use in combination with +conn.get_result+.
1898
+ */
1899
+ static VALUE
1900
+ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
1901
+ {
1902
+ VALUE error;
1903
+ PGconn *conn = pg_get_pgconn(self);
1904
+ /* returns 0 on failure */
1905
+ if(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
1906
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1907
+ rb_iv_set(error, "@connection", self);
1908
+ rb_exc_raise(error);
1909
+ }
1910
+ return Qnil;
1911
+ }
1912
+
1913
+
1914
+ /*
1915
+ * call-seq:
1916
+ * conn.send_describe_portal( portal_name ) -> nil
1917
+ *
1918
+ * Asynchronously send _command_ to the server. Does not block.
1919
+ * Use in combination with +conn.get_result+.
1920
+ */
1921
+ static VALUE
1922
+ pgconn_send_describe_portal(VALUE self, VALUE portal)
1923
+ {
1924
+ VALUE error;
1925
+ PGconn *conn = pg_get_pgconn(self);
1926
+ /* returns 0 on failure */
1927
+ if(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
1928
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1929
+ rb_iv_set(error, "@connection", self);
1930
+ rb_exc_raise(error);
1931
+ }
1932
+ return Qnil;
1933
+ }
1934
+
1935
+
1936
+ /*
1937
+ * call-seq:
1938
+ * conn.get_result() -> PG::Result
1939
+ * conn.get_result() {|pg_result| block }
1940
+ *
1941
+ * Blocks waiting for the next result from a call to
1942
+ * #send_query (or another asynchronous command), and returns
1943
+ * it. Returns +nil+ if no more results are available.
1944
+ *
1945
+ * Note: call this function repeatedly until it returns +nil+, or else
1946
+ * you will not be able to issue further commands.
1947
+ *
1948
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
1949
+ * and the PG::Result object will automatically be cleared when the block terminates.
1950
+ * In this instance, <code>conn.exec</code> returns the value of the block.
1951
+ */
1952
+ static VALUE
1953
+ pgconn_get_result(VALUE self)
1954
+ {
1955
+ PGconn *conn = pg_get_pgconn(self);
1956
+ PGresult *result;
1957
+ VALUE rb_pgresult;
1958
+
1959
+ result = gvl_PQgetResult(conn);
1960
+ if(result == NULL)
1961
+ return Qnil;
1962
+ rb_pgresult = pg_new_result(result, self);
1963
+ if (rb_block_given_p()) {
1964
+ return rb_ensure(rb_yield, rb_pgresult,
1965
+ pg_result_clear, rb_pgresult);
1966
+ }
1967
+ return rb_pgresult;
1968
+ }
1969
+
1970
+ /*
1971
+ * call-seq:
1972
+ * conn.consume_input()
1973
+ *
1974
+ * If input is available from the server, consume it.
1975
+ * After calling +consume_input+, you can check +is_busy+
1976
+ * or *notifies* to see if the state has changed.
1977
+ */
1978
+ static VALUE
1979
+ pgconn_consume_input(self)
1980
+ VALUE self;
1981
+ {
1982
+ VALUE error;
1983
+ PGconn *conn = pg_get_pgconn(self);
1984
+ /* returns 0 on error */
1985
+ if(PQconsumeInput(conn) == 0) {
1986
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1987
+ rb_iv_set(error, "@connection", self);
1988
+ rb_exc_raise(error);
1989
+ }
1990
+ return Qnil;
1991
+ }
1992
+
1993
+ /*
1994
+ * call-seq:
1995
+ * conn.is_busy() -> Boolean
1996
+ *
1997
+ * Returns +true+ if a command is busy, that is, if
1998
+ * PQgetResult would block. Otherwise returns +false+.
1999
+ */
2000
+ static VALUE
2001
+ pgconn_is_busy(self)
2002
+ VALUE self;
2003
+ {
2004
+ return PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2005
+ }
2006
+
2007
+ /*
2008
+ * call-seq:
2009
+ * conn.setnonblocking(Boolean) -> nil
2010
+ *
2011
+ * Sets the nonblocking status of the connection.
2012
+ * In the blocking state, calls to #send_query
2013
+ * will block until the message is sent to the server,
2014
+ * but will not wait for the query results.
2015
+ * In the nonblocking state, calls to #send_query
2016
+ * will return an error if the socket is not ready for
2017
+ * writing.
2018
+ * Note: This function does not affect #exec, because
2019
+ * that function doesn't return until the server has
2020
+ * processed the query and returned the results.
2021
+ * Returns +nil+.
2022
+ */
2023
+ static VALUE
2024
+ pgconn_setnonblocking(self, state)
2025
+ VALUE self, state;
2026
+ {
2027
+ int arg;
2028
+ VALUE error;
2029
+ PGconn *conn = pg_get_pgconn(self);
2030
+ if(state == Qtrue)
2031
+ arg = 1;
2032
+ else if (state == Qfalse)
2033
+ arg = 0;
2034
+ else
2035
+ rb_raise(rb_eArgError, "Boolean value expected");
2036
+
2037
+ if(PQsetnonblocking(conn, arg) == -1) {
2038
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2039
+ rb_iv_set(error, "@connection", self);
2040
+ rb_exc_raise(error);
2041
+ }
2042
+ return Qnil;
2043
+ }
2044
+
2045
+
2046
+ /*
2047
+ * call-seq:
2048
+ * conn.isnonblocking() -> Boolean
2049
+ *
2050
+ * Returns +true+ if a command is busy, that is, if
2051
+ * PQgetResult would block. Otherwise returns +false+.
2052
+ */
2053
+ static VALUE
2054
+ pgconn_isnonblocking(self)
2055
+ VALUE self;
2056
+ {
2057
+ return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2058
+ }
2059
+
2060
+ /*
2061
+ * call-seq:
2062
+ * conn.flush() -> Boolean
2063
+ *
2064
+ * Attempts to flush any queued output data to the server.
2065
+ * Returns +true+ if data is successfully flushed, +false+
2066
+ * if not (can only return +false+ if connection is
2067
+ * nonblocking.
2068
+ * Raises PG::Error if some other failure occurred.
2069
+ */
2070
+ static VALUE
2071
+ pgconn_flush(self)
2072
+ VALUE self;
2073
+ {
2074
+ PGconn *conn = pg_get_pgconn(self);
2075
+ int ret;
2076
+ VALUE error;
2077
+ ret = PQflush(conn);
2078
+ if(ret == -1) {
2079
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2080
+ rb_iv_set(error, "@connection", self);
2081
+ rb_exc_raise(error);
2082
+ }
2083
+ return (ret) ? Qfalse : Qtrue;
2084
+ }
2085
+
2086
+ /*
2087
+ * call-seq:
2088
+ * conn.cancel() -> String
2089
+ *
2090
+ * Requests cancellation of the command currently being
2091
+ * processed. (Only implemented in PostgreSQL >= 8.0)
2092
+ *
2093
+ * Returns +nil+ on success, or a string containing the
2094
+ * error message if a failure occurs.
2095
+ */
2096
+ static VALUE
2097
+ pgconn_cancel(VALUE self)
2098
+ {
2099
+ #ifdef HAVE_PQGETCANCEL
2100
+ char errbuf[256];
2101
+ PGcancel *cancel;
2102
+ VALUE retval;
2103
+ int ret;
2104
+
2105
+ cancel = PQgetCancel(pg_get_pgconn(self));
2106
+ if(cancel == NULL)
2107
+ rb_raise(rb_ePGerror,"Invalid connection!");
2108
+
2109
+ ret = PQcancel(cancel, errbuf, 256);
2110
+ if(ret == 1)
2111
+ retval = Qnil;
2112
+ else
2113
+ retval = rb_str_new2(errbuf);
2114
+
2115
+ PQfreeCancel(cancel);
2116
+ return retval;
2117
+ #else
2118
+ rb_notimplement();
2119
+ #endif
2120
+ }
2121
+
2122
+
2123
+ /*
2124
+ * call-seq:
2125
+ * conn.notifies()
2126
+ *
2127
+ * Returns a hash of the unprocessed notifications.
2128
+ * If there is no unprocessed notifier, it returns +nil+.
2129
+ */
2130
+ static VALUE
2131
+ pgconn_notifies(VALUE self)
2132
+ {
2133
+ PGconn* conn = pg_get_pgconn(self);
2134
+ PGnotify *notification;
2135
+ VALUE hash;
2136
+ VALUE sym_relname, sym_be_pid, sym_extra;
2137
+ VALUE relname, be_pid, extra;
2138
+
2139
+ sym_relname = ID2SYM(rb_intern("relname"));
2140
+ sym_be_pid = ID2SYM(rb_intern("be_pid"));
2141
+ sym_extra = ID2SYM(rb_intern("extra"));
2142
+
2143
+ notification = PQnotifies(conn);
2144
+ if (notification == NULL) {
2145
+ return Qnil;
2146
+ }
2147
+
2148
+ hash = rb_hash_new();
2149
+ relname = rb_tainted_str_new2(notification->relname);
2150
+ be_pid = INT2NUM(notification->be_pid);
2151
+ extra = rb_tainted_str_new2(notification->extra);
2152
+ #ifdef M17N_SUPPORTED
2153
+ ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
2154
+ ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
2155
+ #endif
2156
+
2157
+ rb_hash_aset(hash, sym_relname, relname);
2158
+ rb_hash_aset(hash, sym_be_pid, be_pid);
2159
+ rb_hash_aset(hash, sym_extra, extra);
2160
+
2161
+ PQfreemem(notification);
2162
+ return hash;
2163
+ }
2164
+
2165
+ /* Win32 + Ruby 1.8 */
2166
+ #if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2167
+
2168
+ /*
2169
+ * Duplicate the sockets from libpq and create temporary CRT FDs
2170
+ */
2171
+ void create_crt_fd(fd_set *os_set, fd_set *crt_set)
2172
+ {
2173
+ int i;
2174
+ crt_set->fd_count = os_set->fd_count;
2175
+ for (i = 0; i < os_set->fd_count; i++) {
2176
+ WSAPROTOCOL_INFO wsa_pi;
2177
+ /* dupicate the SOCKET */
2178
+ int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
2179
+ SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
2180
+ /* create the CRT fd so ruby can get back to the SOCKET */
2181
+ int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
2182
+ os_set->fd_array[i] = s;
2183
+ crt_set->fd_array[i] = fd;
2184
+ }
2185
+ }
2186
+
2187
+ /*
2188
+ * Clean up the CRT FDs from create_crt_fd()
2189
+ */
2190
+ void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2191
+ {
2192
+ int i;
2193
+ for (i = 0; i < os_set->fd_count; i++) {
2194
+ /* cleanup the CRT fd */
2195
+ _close(crt_set->fd_array[i]);
2196
+ /* cleanup the duplicated SOCKET */
2197
+ closesocket(os_set->fd_array[i]);
2198
+ }
2199
+ }
2200
+ #endif
2201
+
2202
+ /* Win32 + Ruby 1.9+ */
2203
+ #if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2204
+ /*
2205
+ * On Windows, use platform-specific strategies to wait for the socket
2206
+ * instead of rb_thread_select().
2207
+ */
2208
+
2209
+ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2210
+
2211
+ /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2212
+ * and does not wait (nor sleep) any time even if timeout is given.
2213
+ * Instead use the Winsock events and rb_w32_wait_events(). */
2214
+
2215
+ static void *
2216
+ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2217
+ {
2218
+ int sd = PQsocket( conn );
2219
+ void *retval;
2220
+ DWORD timeout_milisec = INFINITE;
2221
+ DWORD wait_ret;
2222
+ WSAEVENT hEvent;
2223
+
2224
+ if ( sd < 0 )
2225
+ rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
2226
+
2227
+ hEvent = WSACreateEvent();
2228
+
2229
+ if ( ptimeout ) {
2230
+ timeout_milisec = (DWORD)( ptimeout->tv_sec * 1e3 + ptimeout->tv_usec / 1e3 );
2231
+ }
2232
+
2233
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2234
+ if( PQconsumeInput(conn) == 0 ) {
2235
+ WSACloseEvent( hEvent );
2236
+ rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
2237
+ }
2238
+
2239
+ while ( !(retval=is_readable(conn)) ) {
2240
+ if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2241
+ WSACloseEvent( hEvent );
2242
+ rb_raise( rb_ePGerror, "WSAEventSelect socket error: %d", WSAGetLastError() );
2243
+ }
2244
+
2245
+ wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2246
+
2247
+ if ( wait_ret == WAIT_TIMEOUT ) {
2248
+ WSACloseEvent( hEvent );
2249
+ return NULL;
2250
+ } else if ( wait_ret == WAIT_OBJECT_0 ) {
2251
+ /* The event we were waiting for. */
2252
+ } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2253
+ /* This indicates interruption from timer thread, GC, exception
2254
+ * from other threads etc... */
2255
+ rb_thread_check_ints();
2256
+ } else if ( wait_ret == WAIT_FAILED ) {
2257
+ WSACloseEvent( hEvent );
2258
+ rb_raise( rb_ePGerror, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
2259
+ } else {
2260
+ WSACloseEvent( hEvent );
2261
+ rb_raise( rb_ePGerror, "Wait on socket abandoned (WaitForMultipleObjects)" );
2262
+ }
2263
+
2264
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2265
+ if ( PQconsumeInput(conn) == 0 ) {
2266
+ WSACloseEvent( hEvent );
2267
+ rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
2268
+ }
2269
+ }
2270
+
2271
+ WSACloseEvent( hEvent );
2272
+ return retval;
2273
+ }
2274
+
2275
+ #else
2276
+
2277
+ /* non Win32 or Win32+Ruby-1.8 */
2278
+
2279
+ static void *
2280
+ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2281
+ {
2282
+ int sd = PQsocket( conn );
2283
+ int ret;
2284
+ void *retval;
2285
+ rb_fdset_t sd_rset;
2286
+ #ifdef _WIN32
2287
+ rb_fdset_t crt_sd_rset;
2288
+ #endif
2289
+
2290
+ if ( sd < 0 )
2291
+ rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
2292
+
2293
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2294
+ if ( PQconsumeInput(conn) == 0 )
2295
+ rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
2296
+
2297
+ rb_fd_init( &sd_rset );
2298
+
2299
+ while ( !(retval=is_readable(conn)) ) {
2300
+ rb_fd_zero( &sd_rset );
2301
+ rb_fd_set( sd, &sd_rset );
2302
+
2303
+ #ifdef _WIN32
2304
+ /* Ruby's FD_SET is modified on win32 to convert a file descriptor
2305
+ * to osfhandle, but we already get a osfhandle from PQsocket().
2306
+ * Therefore it's overwritten here. */
2307
+ sd_rset.fd_array[0] = sd;
2308
+ create_crt_fd(&sd_rset, &crt_sd_rset);
2309
+ #endif
2310
+
2311
+ /* Wait for the socket to become readable before checking again */
2312
+ ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
2313
+
2314
+ #ifdef _WIN32
2315
+ cleanup_crt_fd(&sd_rset, &crt_sd_rset);
2316
+ #endif
2317
+
2318
+ if ( ret < 0 ){
2319
+ rb_fd_term( &sd_rset );
2320
+ rb_sys_fail( "rb_thread_select()" );
2321
+ }
2322
+
2323
+ /* Return false if the select() timed out */
2324
+ if ( ret == 0 ){
2325
+ rb_fd_term( &sd_rset );
2326
+ return NULL;
2327
+ }
2328
+
2329
+ /* Check for connection errors (PQisBusy is true on connection errors) */
2330
+ if ( PQconsumeInput(conn) == 0 ){
2331
+ rb_fd_term( &sd_rset );
2332
+ rb_raise( rb_ePGerror, "%s", PQerrorMessage(conn) );
2333
+ }
2334
+ }
2335
+
2336
+ rb_fd_term( &sd_rset );
2337
+ return retval;
2338
+ }
2339
+
2340
+
2341
+ #endif
2342
+
2343
+ static void *
2344
+ notify_readable(PGconn *conn)
2345
+ {
2346
+ return (void*)PQnotifies(conn);
2347
+ }
2348
+
2349
+ /*
2350
+ * call-seq:
2351
+ * conn.wait_for_notify( [ timeout ] ) -> String
2352
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
2353
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
2354
+ *
2355
+ * Blocks while waiting for notification(s), or until the optional
2356
+ * _timeout_ is reached, whichever comes first. _timeout_ is
2357
+ * measured in seconds and can be fractional.
2358
+ *
2359
+ * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
2360
+ * event otherwise. If used in block form, passes the name of the
2361
+ * NOTIFY +event+ and the generating +pid+ into the block.
2362
+ *
2363
+ * Under PostgreSQL 9.0 and later, if the notification is sent with
2364
+ * the optional +payload+ string, it will be given to the block as the
2365
+ * third argument.
2366
+ *
2367
+ */
2368
+ static VALUE
2369
+ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2370
+ {
2371
+ PGconn *conn = pg_get_pgconn( self );
2372
+ PGnotify *pnotification;
2373
+ struct timeval timeout;
2374
+ struct timeval *ptimeout = NULL;
2375
+ VALUE timeout_in = Qnil, relname = Qnil, be_pid = Qnil, extra = Qnil;
2376
+ double timeout_sec;
2377
+
2378
+ rb_scan_args( argc, argv, "01", &timeout_in );
2379
+
2380
+ if ( RTEST(timeout_in) ) {
2381
+ timeout_sec = NUM2DBL( timeout_in );
2382
+ timeout.tv_sec = (time_t)timeout_sec;
2383
+ timeout.tv_usec = (suseconds_t)( (timeout_sec - (long)timeout_sec) * 1e6 );
2384
+ ptimeout = &timeout;
2385
+ }
2386
+
2387
+ pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2388
+
2389
+ /* Return nil if the select timed out */
2390
+ if ( !pnotification ) return Qnil;
2391
+
2392
+ relname = rb_tainted_str_new2( pnotification->relname );
2393
+ #ifdef M17N_SUPPORTED
2394
+ ENCODING_SET( relname, rb_enc_to_index(pg_conn_enc_get( conn )) );
2395
+ #endif
2396
+ be_pid = INT2NUM( pnotification->be_pid );
2397
+ #ifdef HAVE_ST_NOTIFY_EXTRA
2398
+ if ( *pnotification->extra ) {
2399
+ extra = rb_tainted_str_new2( pnotification->extra );
2400
+ #ifdef M17N_SUPPORTED
2401
+ ENCODING_SET( extra, rb_enc_to_index(pg_conn_enc_get( conn )) );
2402
+ #endif
2403
+ }
2404
+ #endif
2405
+ PQfreemem( pnotification );
2406
+
2407
+ if ( rb_block_given_p() )
2408
+ rb_yield_values( 3, relname, be_pid, extra );
2409
+
2410
+ return relname;
2411
+ }
2412
+
2413
+
2414
+ /*
2415
+ * call-seq:
2416
+ * conn.put_copy_data( buffer ) -> Boolean
2417
+ *
2418
+ * Transmits _buffer_ as copy data to the server.
2419
+ * Returns true if the data was sent, false if it was
2420
+ * not sent (false is only possible if the connection
2421
+ * is in nonblocking mode, and this command would block).
2422
+ *
2423
+ * Raises an exception if an error occurs.
2424
+ */
2425
+ static VALUE
2426
+ pgconn_put_copy_data(self, buffer)
2427
+ VALUE self, buffer;
2428
+ {
2429
+ int ret;
2430
+ VALUE error;
2431
+ PGconn *conn = pg_get_pgconn(self);
2432
+ Check_Type(buffer, T_STRING);
2433
+
2434
+ ret = gvl_PQputCopyData(conn, RSTRING_PTR(buffer), (int)RSTRING_LEN(buffer));
2435
+ if(ret == -1) {
2436
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2437
+ rb_iv_set(error, "@connection", self);
2438
+ rb_exc_raise(error);
2439
+ }
2440
+ return (ret) ? Qtrue : Qfalse;
2441
+ }
2442
+
2443
+ /*
2444
+ * call-seq:
2445
+ * conn.put_copy_end( [ error_message ] ) -> Boolean
2446
+ *
2447
+ * Sends end-of-data indication to the server.
2448
+ *
2449
+ * _error_message_ is an optional parameter, and if set,
2450
+ * forces the COPY command to fail with the string
2451
+ * _error_message_.
2452
+ *
2453
+ * Returns true if the end-of-data was sent, false if it was
2454
+ * not sent (false is only possible if the connection
2455
+ * is in nonblocking mode, and this command would block).
2456
+ */
2457
+ static VALUE
2458
+ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2459
+ {
2460
+ VALUE str;
2461
+ VALUE error;
2462
+ int ret;
2463
+ char *error_message = NULL;
2464
+ PGconn *conn = pg_get_pgconn(self);
2465
+
2466
+ if (rb_scan_args(argc, argv, "01", &str) == 0)
2467
+ error_message = NULL;
2468
+ else
2469
+ error_message = StringValuePtr(str);
2470
+
2471
+ ret = gvl_PQputCopyEnd(conn, error_message);
2472
+ if(ret == -1) {
2473
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2474
+ rb_iv_set(error, "@connection", self);
2475
+ rb_exc_raise(error);
2476
+ }
2477
+ return (ret) ? Qtrue : Qfalse;
2478
+ }
2479
+
2480
+ /*
2481
+ * call-seq:
2482
+ * conn.get_copy_data( [ async = false ] ) -> String
2483
+ *
2484
+ * Return a string containing one row of data, +nil+
2485
+ * if the copy is done, or +false+ if the call would
2486
+ * block (only possible if _async_ is true).
2487
+ *
2488
+ */
2489
+ static VALUE
2490
+ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2491
+ {
2492
+ VALUE async_in;
2493
+ VALUE error;
2494
+ VALUE result_str;
2495
+ int ret;
2496
+ int async;
2497
+ char *buffer;
2498
+ PGconn *conn = pg_get_pgconn(self);
2499
+
2500
+ if (rb_scan_args(argc, argv, "01", &async_in) == 0)
2501
+ async = 0;
2502
+ else
2503
+ async = (async_in == Qfalse || async_in == Qnil) ? 0 : 1;
2504
+
2505
+ ret = gvl_PQgetCopyData(conn, &buffer, async);
2506
+ if(ret == -2) { /* error */
2507
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2508
+ rb_iv_set(error, "@connection", self);
2509
+ rb_exc_raise(error);
2510
+ }
2511
+ if(ret == -1) { /* No data left */
2512
+ return Qnil;
2513
+ }
2514
+ if(ret == 0) { /* would block */
2515
+ return Qfalse;
2516
+ }
2517
+ result_str = rb_tainted_str_new(buffer, ret);
2518
+ PQfreemem(buffer);
2519
+ return result_str;
2520
+ }
2521
+
2522
+ /*
2523
+ * call-seq:
2524
+ * conn.set_error_verbosity( verbosity ) -> Fixnum
2525
+ *
2526
+ * Sets connection's verbosity to _verbosity_ and returns
2527
+ * the previous setting. Available settings are:
2528
+ * * PQERRORS_TERSE
2529
+ * * PQERRORS_DEFAULT
2530
+ * * PQERRORS_VERBOSE
2531
+ */
2532
+ static VALUE
2533
+ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2534
+ {
2535
+ PGconn *conn = pg_get_pgconn(self);
2536
+ PGVerbosity verbosity = NUM2INT(in_verbosity);
2537
+ return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2538
+ }
2539
+
2540
+ /*
2541
+ * call-seq:
2542
+ * conn.trace( stream ) -> nil
2543
+ *
2544
+ * Enables tracing message passing between backend. The
2545
+ * trace message will be written to the stream _stream_,
2546
+ * which must implement a method +fileno+ that returns
2547
+ * a writable file descriptor.
2548
+ */
2549
+ static VALUE
2550
+ pgconn_trace(VALUE self, VALUE stream)
2551
+ {
2552
+ VALUE fileno;
2553
+ FILE *new_fp;
2554
+ int old_fd, new_fd;
2555
+ VALUE new_file;
2556
+
2557
+ if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2558
+ rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2559
+
2560
+ fileno = rb_funcall(stream, rb_intern("fileno"), 0);
2561
+ if(fileno == Qnil)
2562
+ rb_raise(rb_eArgError, "can't get file descriptor from stream");
2563
+
2564
+ /* Duplicate the file descriptor and re-open
2565
+ * it. Then, make it into a ruby File object
2566
+ * and assign it to an instance variable.
2567
+ * This prevents a problem when the File
2568
+ * object passed to this function is closed
2569
+ * before the connection object is. */
2570
+ old_fd = NUM2INT(fileno);
2571
+ new_fd = dup(old_fd);
2572
+ new_fp = fdopen(new_fd, "w");
2573
+
2574
+ if(new_fp == NULL)
2575
+ rb_raise(rb_eArgError, "stream is not writable");
2576
+
2577
+ new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2578
+ rb_iv_set(self, "@trace_stream", new_file);
2579
+
2580
+ PQtrace(pg_get_pgconn(self), new_fp);
2581
+ return Qnil;
2582
+ }
2583
+
2584
+ /*
2585
+ * call-seq:
2586
+ * conn.untrace() -> nil
2587
+ *
2588
+ * Disables the message tracing.
2589
+ */
2590
+ static VALUE
2591
+ pgconn_untrace(VALUE self)
2592
+ {
2593
+ VALUE trace_stream;
2594
+ PQuntrace(pg_get_pgconn(self));
2595
+ trace_stream = rb_iv_get(self, "@trace_stream");
2596
+ rb_funcall(trace_stream, rb_intern("close"), 0);
2597
+ rb_iv_set(self, "@trace_stream", Qnil);
2598
+ return Qnil;
2599
+ }
2600
+
2601
+
2602
+ /*
2603
+ * Notice callback proxy function -- delegate the callback to the
2604
+ * currently-registered Ruby notice_receiver object.
2605
+ */
2606
+ void
2607
+ notice_receiver_proxy(void *arg, const PGresult *result)
2608
+ {
2609
+ VALUE proc;
2610
+ VALUE self = (VALUE)arg;
2611
+
2612
+ if ((proc = rb_iv_get(self, "@notice_receiver")) != Qnil) {
2613
+ VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, NULL, (PGresult*)result);
2614
+ #ifdef M17N_SUPPORTED
2615
+ PGconn *conn = pg_get_pgconn( self );
2616
+ rb_encoding *enc = pg_conn_enc_get( conn );
2617
+ ENCODING_SET( val, rb_enc_to_index(enc) );
2618
+ #endif
2619
+ rb_funcall(proc, rb_intern("call"), 1, val);
2620
+ }
2621
+ return;
2622
+ }
2623
+
2624
+ /*
2625
+ * call-seq:
2626
+ * conn.set_notice_receiver {|result| ... } -> Proc
2627
+ *
2628
+ * Notice and warning messages generated by the server are not returned
2629
+ * by the query execution functions, since they do not imply failure of
2630
+ * the query. Instead they are passed to a notice handling function, and
2631
+ * execution continues normally after the handler returns. The default
2632
+ * notice handling function prints the message on <tt>stderr</tt>, but the
2633
+ * application can override this behavior by supplying its own handling
2634
+ * function.
2635
+ *
2636
+ * For historical reasons, there are two levels of notice handling, called the
2637
+ * notice receiver and notice processor. The default behavior is for the notice
2638
+ * receiver to format the notice and pass a string to the notice processor for
2639
+ * printing. However, an application that chooses to provide its own notice
2640
+ * receiver will typically ignore the notice processor layer and just do all
2641
+ * the work in the notice receiver.
2642
+ *
2643
+ * This function takes a new block to act as the handler, which should
2644
+ * accept a single parameter that will be a PG::Result object, and returns
2645
+ * the Proc object previously set, or +nil+ if it was previously the default.
2646
+ *
2647
+ * If you pass no arguments, it will reset the handler to the default.
2648
+ *
2649
+ * *Note:* The +result+ passed to the block should not be used outside
2650
+ * of the block, since the corresponding C object could be freed after the
2651
+ * block finishes.
2652
+ */
2653
+ static VALUE
2654
+ pgconn_set_notice_receiver(VALUE self)
2655
+ {
2656
+ VALUE proc, old_proc;
2657
+ PGconn *conn = pg_get_pgconn(self);
2658
+
2659
+ /* If default_notice_receiver is unset, assume that the current
2660
+ * notice receiver is the default, and save it to a global variable.
2661
+ * This should not be a problem because the default receiver is
2662
+ * always the same, so won't vary among connections.
2663
+ */
2664
+ if(default_notice_receiver == NULL)
2665
+ default_notice_receiver = PQsetNoticeReceiver(conn, NULL, NULL);
2666
+
2667
+ old_proc = rb_iv_get(self, "@notice_receiver");
2668
+ if( rb_block_given_p() ) {
2669
+ proc = rb_block_proc();
2670
+ PQsetNoticeReceiver(conn, gvl_notice_receiver_proxy, (void *)self);
2671
+ } else {
2672
+ /* if no block is given, set back to default */
2673
+ proc = Qnil;
2674
+ PQsetNoticeReceiver(conn, default_notice_receiver, NULL);
2675
+ }
2676
+
2677
+ rb_iv_set(self, "@notice_receiver", proc);
2678
+ return old_proc;
2679
+ }
2680
+
2681
+
2682
+ /*
2683
+ * Notice callback proxy function -- delegate the callback to the
2684
+ * currently-registered Ruby notice_processor object.
2685
+ */
2686
+ void
2687
+ notice_processor_proxy(void *arg, const char *message)
2688
+ {
2689
+ VALUE proc;
2690
+ VALUE self = (VALUE)arg;
2691
+
2692
+ if ((proc = rb_iv_get(self, "@notice_processor")) != Qnil) {
2693
+ VALUE message_str = rb_tainted_str_new2(message);
2694
+ #ifdef M17N_SUPPORTED
2695
+ PGconn *conn = pg_get_pgconn( self );
2696
+ rb_encoding *enc = pg_conn_enc_get( conn );
2697
+ ENCODING_SET( message_str, rb_enc_to_index(enc) );
2698
+ #endif
2699
+ rb_funcall(proc, rb_intern("call"), 1, message_str);
2700
+ }
2701
+ return;
2702
+ }
2703
+
2704
+ /*
2705
+ * call-seq:
2706
+ * conn.set_notice_processor {|message| ... } -> Proc
2707
+ *
2708
+ * See #set_notice_receiver for the desription of what this and the
2709
+ * notice_processor methods do.
2710
+ *
2711
+ * This function takes a new block to act as the notice processor and returns
2712
+ * the Proc object previously set, or +nil+ if it was previously the default.
2713
+ * The block should accept a single String object.
2714
+ *
2715
+ * If you pass no arguments, it will reset the handler to the default.
2716
+ */
2717
+ static VALUE
2718
+ pgconn_set_notice_processor(VALUE self)
2719
+ {
2720
+ VALUE proc, old_proc;
2721
+ PGconn *conn = pg_get_pgconn(self);
2722
+
2723
+ /* If default_notice_processor is unset, assume that the current
2724
+ * notice processor is the default, and save it to a global variable.
2725
+ * This should not be a problem because the default processor is
2726
+ * always the same, so won't vary among connections.
2727
+ */
2728
+ if(default_notice_processor == NULL)
2729
+ default_notice_processor = PQsetNoticeProcessor(conn, NULL, NULL);
2730
+
2731
+ old_proc = rb_iv_get(self, "@notice_processor");
2732
+ if( rb_block_given_p() ) {
2733
+ proc = rb_block_proc();
2734
+ PQsetNoticeProcessor(conn, gvl_notice_processor_proxy, (void *)self);
2735
+ } else {
2736
+ /* if no block is given, set back to default */
2737
+ proc = Qnil;
2738
+ PQsetNoticeProcessor(conn, default_notice_processor, NULL);
2739
+ }
2740
+
2741
+ rb_iv_set(self, "@notice_processor", proc);
2742
+ return old_proc;
2743
+ }
2744
+
2745
+
2746
+ /*
2747
+ * call-seq:
2748
+ * conn.get_client_encoding() -> String
2749
+ *
2750
+ * Returns the client encoding as a String.
2751
+ */
2752
+ static VALUE
2753
+ pgconn_get_client_encoding(VALUE self)
2754
+ {
2755
+ char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2756
+ return rb_tainted_str_new2(encoding);
2757
+ }
2758
+
2759
+
2760
+ /*
2761
+ * call-seq:
2762
+ * conn.set_client_encoding( encoding )
2763
+ *
2764
+ * Sets the client encoding to the _encoding_ String.
2765
+ */
2766
+ static VALUE
2767
+ pgconn_set_client_encoding(VALUE self, VALUE str)
2768
+ {
2769
+ PGconn *conn = pg_get_pgconn( self );
2770
+
2771
+ Check_Type(str, T_STRING);
2772
+
2773
+ if ( (PQsetClientEncoding(conn, StringValuePtr(str))) == -1 ) {
2774
+ rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValuePtr(str));
2775
+ }
2776
+
2777
+ return Qnil;
2778
+ }
2779
+
2780
+ /*
2781
+ * call-seq:
2782
+ * conn.transaction { |conn| ... } -> nil
2783
+ *
2784
+ * Executes a +BEGIN+ at the start of the block,
2785
+ * and a +COMMIT+ at the end of the block, or
2786
+ * +ROLLBACK+ if any exception occurs.
2787
+ */
2788
+ static VALUE
2789
+ pgconn_transaction(VALUE self)
2790
+ {
2791
+ PGconn *conn = pg_get_pgconn(self);
2792
+ PGresult *result;
2793
+ VALUE rb_pgresult;
2794
+ int status;
2795
+
2796
+ if (rb_block_given_p()) {
2797
+ result = gvl_PQexec(conn, "BEGIN");
2798
+ rb_pgresult = pg_new_result(result, self);
2799
+ pg_result_check(rb_pgresult);
2800
+ rb_protect(rb_yield, self, &status);
2801
+ if(status == 0) {
2802
+ result = gvl_PQexec(conn, "COMMIT");
2803
+ rb_pgresult = pg_new_result(result, self);
2804
+ pg_result_check(rb_pgresult);
2805
+ }
2806
+ else {
2807
+ /* exception occurred, ROLLBACK and re-raise */
2808
+ result = gvl_PQexec(conn, "ROLLBACK");
2809
+ rb_pgresult = pg_new_result(result, self);
2810
+ pg_result_check(rb_pgresult);
2811
+ rb_jump_tag(status);
2812
+ }
2813
+
2814
+ }
2815
+ else {
2816
+ /* no block supplied? */
2817
+ rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
2818
+ }
2819
+ return Qnil;
2820
+ }
2821
+
2822
+
2823
+ /*
2824
+ * call-seq:
2825
+ * PG::Connection.quote_ident( str ) -> String
2826
+ * conn.quote_ident( str ) -> String
2827
+ *
2828
+ * Returns a string that is safe for inclusion in a SQL query as an
2829
+ * identifier. Note: this is not a quote function for values, but for
2830
+ * identifiers.
2831
+ *
2832
+ * For example, in a typical SQL query: <tt>SELECT FOO FROM MYTABLE</tt>
2833
+ * The identifier <tt>FOO</tt> is folded to lower case, so it actually
2834
+ * means <tt>foo</tt>. If you really want to access the case-sensitive
2835
+ * field name <tt>FOO</tt>, use this function like
2836
+ * <tt>PG::Connection.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
2837
+ * (with double-quotes). PostgreSQL will see the double-quotes, and
2838
+ * it will not fold to lower case.
2839
+ *
2840
+ * Similarly, this function also protects against special characters,
2841
+ * and other things that might allow SQL injection if the identifier
2842
+ * comes from an untrusted source.
2843
+ */
2844
+ static VALUE
2845
+ pgconn_s_quote_ident(VALUE self, VALUE in_str)
2846
+ {
2847
+ VALUE ret;
2848
+ char *str = StringValuePtr(in_str);
2849
+ /* result size at most NAMEDATALEN*2 plus surrounding
2850
+ * double-quotes. */
2851
+ char buffer[NAMEDATALEN*2+2];
2852
+ unsigned int i=0,j=0;
2853
+
2854
+ UNUSED( self );
2855
+
2856
+ if(strlen(str) >= NAMEDATALEN) {
2857
+ rb_raise(rb_eArgError,
2858
+ "Input string is longer than NAMEDATALEN-1 (%d)",
2859
+ NAMEDATALEN-1);
2860
+ }
2861
+ buffer[j++] = '"';
2862
+ for(i = 0; i < strlen(str) && str[i]; i++) {
2863
+ if(str[i] == '"')
2864
+ buffer[j++] = '"';
2865
+ buffer[j++] = str[i];
2866
+ }
2867
+ buffer[j++] = '"';
2868
+ ret = rb_str_new(buffer,j);
2869
+ OBJ_INFECT(ret, in_str);
2870
+ return ret;
2871
+ }
2872
+
2873
+
2874
+ static void *
2875
+ get_result_readable(PGconn *conn)
2876
+ {
2877
+ return PQisBusy(conn) ? NULL : (void*)1;
2878
+ }
2879
+
2880
+
2881
+ /*
2882
+ * call-seq:
2883
+ * conn.block( [ timeout ] ) -> Boolean
2884
+ *
2885
+ * Blocks until the server is no longer busy, or until the
2886
+ * optional _timeout_ is reached, whichever comes first.
2887
+ * _timeout_ is measured in seconds and can be fractional.
2888
+ *
2889
+ * Returns +false+ if _timeout_ is reached, +true+ otherwise.
2890
+ *
2891
+ * If +true+ is returned, +conn.is_busy+ will return +false+
2892
+ * and +conn.get_result+ will not block.
2893
+ */
2894
+ static VALUE
2895
+ pgconn_block( int argc, VALUE *argv, VALUE self ) {
2896
+ PGconn *conn = pg_get_pgconn( self );
2897
+
2898
+ /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2899
+ * and does not wait (nor sleep) any time even if timeout is given.
2900
+ * Instead use the Winsock events and rb_w32_wait_events(). */
2901
+
2902
+ struct timeval timeout;
2903
+ struct timeval *ptimeout = NULL;
2904
+ VALUE timeout_in;
2905
+ double timeout_sec;
2906
+ void *ret;
2907
+
2908
+ if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2909
+ timeout_sec = NUM2DBL( timeout_in );
2910
+ timeout.tv_sec = (time_t)timeout_sec;
2911
+ timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
2912
+ ptimeout = &timeout;
2913
+ }
2914
+
2915
+ ret = wait_socket_readable( conn, ptimeout, get_result_readable);
2916
+
2917
+ if( !ret )
2918
+ return Qfalse;
2919
+
2920
+ return Qtrue;
2921
+ }
2922
+
2923
+
2924
+ /*
2925
+ * call-seq:
2926
+ * conn.get_last_result( ) -> PG::Result
2927
+ *
2928
+ * This function retrieves all available results
2929
+ * on the current connection (from previously issued
2930
+ * asynchronous commands like +send_query()+) and
2931
+ * returns the last non-NULL result, or +nil+ if no
2932
+ * results are available.
2933
+ *
2934
+ * This function is similar to #get_result
2935
+ * except that it is designed to get one and only
2936
+ * one result.
2937
+ */
2938
+ static VALUE
2939
+ pgconn_get_last_result(VALUE self)
2940
+ {
2941
+ PGconn *conn = pg_get_pgconn(self);
2942
+ VALUE rb_pgresult = Qnil;
2943
+ PGresult *cur, *prev;
2944
+
2945
+
2946
+ cur = prev = NULL;
2947
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
2948
+ int status;
2949
+
2950
+ if (prev) PQclear(prev);
2951
+ prev = cur;
2952
+
2953
+ status = PQresultStatus(cur);
2954
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
2955
+ break;
2956
+ }
2957
+
2958
+ if (prev) {
2959
+ rb_pgresult = pg_new_result( prev, self );
2960
+ pg_result_check(rb_pgresult);
2961
+ }
2962
+
2963
+ return rb_pgresult;
2964
+ }
2965
+
2966
+ #if !defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
2967
+
2968
+ /*
2969
+ * call-seq:
2970
+ * conn.async_exec(sql [, params, result_format ] ) -> PG::Result
2971
+ * conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
2972
+ *
2973
+ * This function has the same behavior as #exec,
2974
+ * but ensures that other threads can process while
2975
+ * waiting for the server to complete the request.
2976
+ *
2977
+ * On Ruby platforms with native threads (MRI-1.9+ and all others)
2978
+ * this method is an alias to #exec.
2979
+ *
2980
+ * On MRI-1.8 it's implemented using asynchronous command
2981
+ * processing and ruby's +rb_thread_select+ .
2982
+ */
2983
+ static VALUE
2984
+ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
2985
+ {
2986
+ VALUE rb_pgresult = Qnil;
2987
+
2988
+ /* remove any remaining results from the queue */
2989
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
2990
+ pgconn_get_last_result( self );
2991
+
2992
+ pgconn_send_query( argc, argv, self );
2993
+ pgconn_block( 0, NULL, self );
2994
+ rb_pgresult = pgconn_get_last_result( self );
2995
+
2996
+ if ( rb_block_given_p() ) {
2997
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
2998
+ }
2999
+ return rb_pgresult;
3000
+ }
3001
+
3002
+ #endif
3003
+
3004
+ /**************************************************************************
3005
+ * LARGE OBJECT SUPPORT
3006
+ **************************************************************************/
3007
+
3008
+ /*
3009
+ * call-seq:
3010
+ * conn.lo_creat( [mode] ) -> Fixnum
3011
+ *
3012
+ * Creates a large object with mode _mode_. Returns a large object Oid.
3013
+ * On failure, it raises PG::Error.
3014
+ */
3015
+ static VALUE
3016
+ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3017
+ {
3018
+ Oid lo_oid;
3019
+ int mode;
3020
+ VALUE nmode;
3021
+ PGconn *conn = pg_get_pgconn(self);
3022
+
3023
+ if (rb_scan_args(argc, argv, "01", &nmode) == 0)
3024
+ mode = INV_READ;
3025
+ else
3026
+ mode = NUM2INT(nmode);
3027
+
3028
+ lo_oid = lo_creat(conn, mode);
3029
+ if (lo_oid == 0)
3030
+ rb_raise(rb_ePGerror, "lo_creat failed");
3031
+
3032
+ return INT2FIX(lo_oid);
3033
+ }
3034
+
3035
+ /*
3036
+ * call-seq:
3037
+ * conn.lo_create( oid ) -> Fixnum
3038
+ *
3039
+ * Creates a large object with oid _oid_. Returns the large object Oid.
3040
+ * On failure, it raises PG::Error.
3041
+ */
3042
+ static VALUE
3043
+ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3044
+ {
3045
+ Oid ret, lo_oid;
3046
+ PGconn *conn = pg_get_pgconn(self);
3047
+ lo_oid = NUM2INT(in_lo_oid);
3048
+
3049
+ ret = lo_create(conn, lo_oid);
3050
+ if (ret == InvalidOid)
3051
+ rb_raise(rb_ePGerror, "lo_create failed");
3052
+
3053
+ return INT2FIX(ret);
3054
+ }
3055
+
3056
+ /*
3057
+ * call-seq:
3058
+ * conn.lo_import(file) -> Fixnum
3059
+ *
3060
+ * Import a file to a large object. Returns a large object Oid.
3061
+ *
3062
+ * On failure, it raises a PG::Error.
3063
+ */
3064
+ static VALUE
3065
+ pgconn_loimport(VALUE self, VALUE filename)
3066
+ {
3067
+ Oid lo_oid;
3068
+
3069
+ PGconn *conn = pg_get_pgconn(self);
3070
+
3071
+ Check_Type(filename, T_STRING);
3072
+
3073
+ lo_oid = lo_import(conn, StringValuePtr(filename));
3074
+ if (lo_oid == 0) {
3075
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3076
+ }
3077
+ return INT2FIX(lo_oid);
3078
+ }
3079
+
3080
+ /*
3081
+ * call-seq:
3082
+ * conn.lo_export( oid, file ) -> nil
3083
+ *
3084
+ * Saves a large object of _oid_ to a _file_.
3085
+ */
3086
+ static VALUE
3087
+ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3088
+ {
3089
+ PGconn *conn = pg_get_pgconn(self);
3090
+ int oid;
3091
+ Check_Type(filename, T_STRING);
3092
+
3093
+ oid = NUM2INT(lo_oid);
3094
+ if (oid < 0) {
3095
+ rb_raise(rb_ePGerror, "invalid large object oid %d",oid);
3096
+ }
3097
+
3098
+ if (lo_export(conn, oid, StringValuePtr(filename)) < 0) {
3099
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3100
+ }
3101
+ return Qnil;
3102
+ }
3103
+
3104
+ /*
3105
+ * call-seq:
3106
+ * conn.lo_open( oid, [mode] ) -> Fixnum
3107
+ *
3108
+ * Open a large object of _oid_. Returns a large object descriptor
3109
+ * instance on success. The _mode_ argument specifies the mode for
3110
+ * the opened large object,which is either +INV_READ+, or +INV_WRITE+.
3111
+ *
3112
+ * If _mode_ is omitted, the default is +INV_READ+.
3113
+ */
3114
+ static VALUE
3115
+ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3116
+ {
3117
+ Oid lo_oid;
3118
+ int fd, mode;
3119
+ VALUE nmode, selfid;
3120
+ PGconn *conn = pg_get_pgconn(self);
3121
+
3122
+ rb_scan_args(argc, argv, "11", &selfid, &nmode);
3123
+ lo_oid = NUM2INT(selfid);
3124
+ if(NIL_P(nmode))
3125
+ mode = INV_READ;
3126
+ else
3127
+ mode = NUM2INT(nmode);
3128
+
3129
+ if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3130
+ rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3131
+ }
3132
+ return INT2FIX(fd);
3133
+ }
3134
+
3135
+ /*
3136
+ * call-seq:
3137
+ * conn.lo_write( lo_desc, buffer ) -> Fixnum
3138
+ *
3139
+ * Writes the string _buffer_ to the large object _lo_desc_.
3140
+ * Returns the number of bytes written.
3141
+ */
3142
+ static VALUE
3143
+ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3144
+ {
3145
+ int n;
3146
+ PGconn *conn = pg_get_pgconn(self);
3147
+ int fd = NUM2INT(in_lo_desc);
3148
+
3149
+ Check_Type(buffer, T_STRING);
3150
+
3151
+ if( RSTRING_LEN(buffer) < 0) {
3152
+ rb_raise(rb_ePGerror, "write buffer zero string");
3153
+ }
3154
+ if((n = lo_write(conn, fd, StringValuePtr(buffer),
3155
+ RSTRING_LEN(buffer))) < 0) {
3156
+ rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3157
+ }
3158
+
3159
+ return INT2FIX(n);
3160
+ }
3161
+
3162
+ /*
3163
+ * call-seq:
3164
+ * conn.lo_read( lo_desc, len ) -> String
3165
+ *
3166
+ * Attempts to read _len_ bytes from large object _lo_desc_,
3167
+ * returns resulting data.
3168
+ */
3169
+ static VALUE
3170
+ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3171
+ {
3172
+ int ret;
3173
+ PGconn *conn = pg_get_pgconn(self);
3174
+ int len = NUM2INT(in_len);
3175
+ int lo_desc = NUM2INT(in_lo_desc);
3176
+ VALUE str;
3177
+ char *buffer;
3178
+
3179
+ buffer = ALLOC_N(char, len);
3180
+ if(buffer == NULL)
3181
+ rb_raise(rb_eNoMemError, "ALLOC failed!");
3182
+
3183
+ if (len < 0){
3184
+ rb_raise(rb_ePGerror,"nagative length %d given", len);
3185
+ }
3186
+
3187
+ if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3188
+ rb_raise(rb_ePGerror, "lo_read failed");
3189
+
3190
+ if(ret == 0) {
3191
+ xfree(buffer);
3192
+ return Qnil;
3193
+ }
3194
+
3195
+ str = rb_tainted_str_new(buffer, ret);
3196
+ xfree(buffer);
3197
+
3198
+ return str;
3199
+ }
3200
+
3201
+
3202
+ /*
3203
+ * call-seq:
3204
+ * conn.lo_lseek( lo_desc, offset, whence ) -> Fixnum
3205
+ *
3206
+ * Move the large object pointer _lo_desc_ to offset _offset_.
3207
+ * Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
3208
+ * (Or 0, 1, or 2.)
3209
+ */
3210
+ static VALUE
3211
+ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3212
+ {
3213
+ PGconn *conn = pg_get_pgconn(self);
3214
+ int lo_desc = NUM2INT(in_lo_desc);
3215
+ int ret;
3216
+
3217
+ if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3218
+ rb_raise(rb_ePGerror, "lo_lseek failed");
3219
+ }
3220
+
3221
+ return INT2FIX(ret);
3222
+ }
3223
+
3224
+ /*
3225
+ * call-seq:
3226
+ * conn.lo_tell( lo_desc ) -> Fixnum
3227
+ *
3228
+ * Returns the current position of the large object _lo_desc_.
3229
+ */
3230
+ static VALUE
3231
+ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3232
+ {
3233
+ int position;
3234
+ PGconn *conn = pg_get_pgconn(self);
3235
+ int lo_desc = NUM2INT(in_lo_desc);
3236
+
3237
+ if((position = lo_tell(conn, lo_desc)) < 0)
3238
+ rb_raise(rb_ePGerror,"lo_tell failed");
3239
+
3240
+ return INT2FIX(position);
3241
+ }
3242
+
3243
+ /*
3244
+ * call-seq:
3245
+ * conn.lo_truncate( lo_desc, len ) -> nil
3246
+ *
3247
+ * Truncates the large object _lo_desc_ to size _len_.
3248
+ */
3249
+ static VALUE
3250
+ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3251
+ {
3252
+ PGconn *conn = pg_get_pgconn(self);
3253
+ int lo_desc = NUM2INT(in_lo_desc);
3254
+ size_t len = NUM2INT(in_len);
3255
+
3256
+ if(lo_truncate(conn,lo_desc,len) < 0)
3257
+ rb_raise(rb_ePGerror,"lo_truncate failed");
3258
+
3259
+ return Qnil;
3260
+ }
3261
+
3262
+ /*
3263
+ * call-seq:
3264
+ * conn.lo_close( lo_desc ) -> nil
3265
+ *
3266
+ * Closes the postgres large object of _lo_desc_.
3267
+ */
3268
+ static VALUE
3269
+ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3270
+ {
3271
+ PGconn *conn = pg_get_pgconn(self);
3272
+ int lo_desc = NUM2INT(in_lo_desc);
3273
+
3274
+ if(lo_close(conn,lo_desc) < 0)
3275
+ rb_raise(rb_ePGerror,"lo_close failed");
3276
+
3277
+ return Qnil;
3278
+ }
3279
+
3280
+ /*
3281
+ * call-seq:
3282
+ * conn.lo_unlink( oid ) -> nil
3283
+ *
3284
+ * Unlinks (deletes) the postgres large object of _oid_.
3285
+ */
3286
+ static VALUE
3287
+ pgconn_lounlink(VALUE self, VALUE in_oid)
3288
+ {
3289
+ PGconn *conn = pg_get_pgconn(self);
3290
+ int oid = NUM2INT(in_oid);
3291
+
3292
+ if (oid < 0)
3293
+ rb_raise(rb_ePGerror, "invalid oid %d",oid);
3294
+
3295
+ if(lo_unlink(conn,oid) < 0)
3296
+ rb_raise(rb_ePGerror,"lo_unlink failed");
3297
+
3298
+ return Qnil;
3299
+ }
3300
+
3301
+
3302
+ #ifdef M17N_SUPPORTED
3303
+
3304
+ /*
3305
+ * call-seq:
3306
+ * conn.internal_encoding -> Encoding
3307
+ *
3308
+ * defined in Ruby 1.9 or later.
3309
+ *
3310
+ * Returns:
3311
+ * * an Encoding - client_encoding of the connection as a Ruby Encoding object.
3312
+ * * nil - the client_encoding is 'SQL_ASCII'
3313
+ */
3314
+ static VALUE
3315
+ pgconn_internal_encoding(VALUE self)
3316
+ {
3317
+ PGconn *conn = pg_get_pgconn( self );
3318
+ rb_encoding *enc = pg_conn_enc_get( conn );
3319
+
3320
+ if ( enc ) {
3321
+ return rb_enc_from_encoding( enc );
3322
+ } else {
3323
+ return Qnil;
3324
+ }
3325
+ }
3326
+
3327
+ static VALUE pgconn_external_encoding(VALUE self);
3328
+
3329
+ /*
3330
+ * call-seq:
3331
+ * conn.internal_encoding = value
3332
+ *
3333
+ * A wrapper of #set_client_encoding.
3334
+ * defined in Ruby 1.9 or later.
3335
+ *
3336
+ * +value+ can be one of:
3337
+ * * an Encoding
3338
+ * * a String - a name of Encoding
3339
+ * * +nil+ - sets the client_encoding to SQL_ASCII.
3340
+ */
3341
+ static VALUE
3342
+ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3343
+ {
3344
+ if (NIL_P(enc)) {
3345
+ pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3346
+ return enc;
3347
+ }
3348
+ else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", RSTRING_PTR(enc)) == 0 ) {
3349
+ pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3350
+ return enc;
3351
+ }
3352
+ else {
3353
+ rb_encoding *rbenc = rb_to_encoding( enc );
3354
+ const char *name = pg_get_rb_encoding_as_pg_encoding( rbenc );
3355
+
3356
+ if ( PQsetClientEncoding(pg_get_pgconn( self ), name) == -1 ) {
3357
+ VALUE server_encoding = pgconn_external_encoding( self );
3358
+ rb_raise( rb_eEncCompatError, "incompatible character encodings: %s and %s",
3359
+ rb_enc_name(rb_to_encoding(server_encoding)), name );
3360
+ }
3361
+ return enc;
3362
+ }
3363
+
3364
+ rb_raise( rb_ePGerror, "unknown encoding: %s", RSTRING_PTR(rb_inspect(enc)) );
3365
+
3366
+ return Qnil;
3367
+ }
3368
+
3369
+
3370
+
3371
+ /*
3372
+ * call-seq:
3373
+ * conn.external_encoding() -> Encoding
3374
+ *
3375
+ * Return the +server_encoding+ of the connected database as a Ruby Encoding object.
3376
+ * The <tt>SQL_ASCII</tt> encoding is mapped to to <tt>ASCII_8BIT</tt>.
3377
+ */
3378
+ static VALUE
3379
+ pgconn_external_encoding(VALUE self)
3380
+ {
3381
+ PGconn *conn = pg_get_pgconn( self );
3382
+ VALUE encoding = rb_iv_get( self, "@external_encoding" );
3383
+ rb_encoding *enc = NULL;
3384
+ const char *pg_encname = NULL;
3385
+
3386
+ /* Use cached value if found */
3387
+ if ( RTEST(encoding) ) return encoding;
3388
+
3389
+ pg_encname = PQparameterStatus( conn, "server_encoding" );
3390
+ enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3391
+ encoding = rb_enc_from_encoding( enc );
3392
+
3393
+ rb_iv_set( self, "@external_encoding", encoding );
3394
+
3395
+ return encoding;
3396
+ }
3397
+
3398
+
3399
+
3400
+ /*
3401
+ * call-seq:
3402
+ * conn.set_default_encoding() -> Encoding
3403
+ *
3404
+ * If Ruby has its Encoding.default_internal set, set PostgreSQL's client_encoding
3405
+ * to match. Returns the new Encoding, or +nil+ if the default internal encoding
3406
+ * wasn't set.
3407
+ */
3408
+ static VALUE
3409
+ pgconn_set_default_encoding( VALUE self )
3410
+ {
3411
+ PGconn *conn = pg_get_pgconn( self );
3412
+ rb_encoding *enc;
3413
+ const char *encname;
3414
+
3415
+ if (( enc = rb_default_internal_encoding() )) {
3416
+ encname = pg_get_rb_encoding_as_pg_encoding( enc );
3417
+ if ( PQsetClientEncoding(conn, encname) != 0 )
3418
+ rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
3419
+ encname, PQerrorMessage(conn) );
3420
+ return rb_enc_from_encoding( enc );
3421
+ } else {
3422
+ return Qnil;
3423
+ }
3424
+ }
3425
+
3426
+
3427
+ #endif /* M17N_SUPPORTED */
3428
+
3429
+
3430
+
3431
+ void
3432
+ init_pg_connection()
3433
+ {
3434
+ rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
3435
+ rb_include_module(rb_cPGconn, rb_mPGconstants);
3436
+
3437
+ /****** PG::Connection CLASS METHODS ******/
3438
+ rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
3439
+
3440
+ SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
3441
+ SINGLETON_ALIAS(rb_cPGconn, "open", "new");
3442
+ SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
3443
+ SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
3444
+ rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3445
+ SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
3446
+ rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
3447
+ rb_define_singleton_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
3448
+ rb_define_singleton_method(rb_cPGconn, "encrypt_password", pgconn_s_encrypt_password, 2);
3449
+ rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3450
+ rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
3451
+ rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
3452
+ #ifdef HAVE_PQPING
3453
+ rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
3454
+ #endif
3455
+
3456
+ /****** PG::Connection INSTANCE METHODS: Connection Control ******/
3457
+ rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
3458
+ rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
3459
+ rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
3460
+ rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
3461
+ rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
3462
+ rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
3463
+ rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
3464
+ rb_define_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
3465
+ rb_define_alias(rb_cPGconn, "close", "finish");
3466
+
3467
+ /****** PG::Connection INSTANCE METHODS: Connection Status ******/
3468
+ rb_define_method(rb_cPGconn, "db", pgconn_db, 0);
3469
+ rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
3470
+ rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
3471
+ rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
3472
+ rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
3473
+ rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
3474
+ rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
3475
+ rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
3476
+ rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
3477
+ rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
3478
+ rb_define_method(rb_cPGconn, "protocol_version", pgconn_protocol_version, 0);
3479
+ rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
3480
+ rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
3481
+ rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
3482
+ #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
3483
+ rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
3484
+ #endif
3485
+ rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
3486
+ rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
3487
+ rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
3488
+ /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
3489
+
3490
+ /****** PG::Connection INSTANCE METHODS: Command Execution ******/
3491
+ rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
3492
+ rb_define_alias(rb_cPGconn, "query", "exec");
3493
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_exec_params, -1);
3494
+ rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
3495
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
3496
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
3497
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
3498
+ rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
3499
+ rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3500
+ rb_define_alias(rb_cPGconn, "escape", "escape_string");
3501
+ #ifdef HAVE_PQESCAPELITERAL
3502
+ rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
3503
+ #endif
3504
+ #ifdef HAVE_PQESCAPEIDENTIFIER
3505
+ rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
3506
+ #endif
3507
+ rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
3508
+ rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
3509
+ #ifdef HAVE_PQSETSINGLEROWMODE
3510
+ rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
3511
+ #endif
3512
+
3513
+ /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
3514
+ rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
3515
+ rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
3516
+ rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
3517
+ rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
3518
+ rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
3519
+ rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
3520
+ rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
3521
+ rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
3522
+ rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
3523
+ rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
3524
+ rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
3525
+ rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
3526
+
3527
+ /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
3528
+ rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
3529
+
3530
+ /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
3531
+ rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
3532
+
3533
+ /****** PG::Connection INSTANCE METHODS: COPY ******/
3534
+ rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, 1);
3535
+ rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
3536
+ rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
3537
+
3538
+ /****** PG::Connection INSTANCE METHODS: Control Functions ******/
3539
+ rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
3540
+ rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
3541
+ rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
3542
+
3543
+ /****** PG::Connection INSTANCE METHODS: Notice Processing ******/
3544
+ rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
3545
+ rb_define_method(rb_cPGconn, "set_notice_processor", pgconn_set_notice_processor, 0);
3546
+
3547
+ /****** PG::Connection INSTANCE METHODS: Other ******/
3548
+ rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
3549
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
3550
+ rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
3551
+ rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
3552
+ rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
3553
+ rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
3554
+ rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
3555
+ rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3556
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
3557
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
3558
+ #else
3559
+ rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
3560
+ #endif
3561
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
3562
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
3563
+
3564
+ /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
3565
+ rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
3566
+ rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
3567
+ rb_define_method(rb_cPGconn, "lo_create", pgconn_locreate, 1);
3568
+ rb_define_alias(rb_cPGconn, "locreate", "lo_create");
3569
+ rb_define_method(rb_cPGconn, "lo_import", pgconn_loimport, 1);
3570
+ rb_define_alias(rb_cPGconn, "loimport", "lo_import");
3571
+ rb_define_method(rb_cPGconn, "lo_export", pgconn_loexport, 2);
3572
+ rb_define_alias(rb_cPGconn, "loexport", "lo_export");
3573
+ rb_define_method(rb_cPGconn, "lo_open", pgconn_loopen, -1);
3574
+ rb_define_alias(rb_cPGconn, "loopen", "lo_open");
3575
+ rb_define_method(rb_cPGconn, "lo_write",pgconn_lowrite, 2);
3576
+ rb_define_alias(rb_cPGconn, "lowrite", "lo_write");
3577
+ rb_define_method(rb_cPGconn, "lo_read",pgconn_loread, 2);
3578
+ rb_define_alias(rb_cPGconn, "loread", "lo_read");
3579
+ rb_define_method(rb_cPGconn, "lo_lseek",pgconn_lolseek, 3);
3580
+ rb_define_alias(rb_cPGconn, "lolseek", "lo_lseek");
3581
+ rb_define_alias(rb_cPGconn, "lo_seek", "lo_lseek");
3582
+ rb_define_alias(rb_cPGconn, "loseek", "lo_lseek");
3583
+ rb_define_method(rb_cPGconn, "lo_tell",pgconn_lotell, 1);
3584
+ rb_define_alias(rb_cPGconn, "lotell", "lo_tell");
3585
+ rb_define_method(rb_cPGconn, "lo_truncate", pgconn_lotruncate, 2);
3586
+ rb_define_alias(rb_cPGconn, "lotruncate", "lo_truncate");
3587
+ rb_define_method(rb_cPGconn, "lo_close",pgconn_loclose, 1);
3588
+ rb_define_alias(rb_cPGconn, "loclose", "lo_close");
3589
+ rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
3590
+ rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
3591
+
3592
+ #ifdef M17N_SUPPORTED
3593
+ rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
3594
+ rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
3595
+ rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
3596
+ rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
3597
+ #endif /* M17N_SUPPORTED */
3598
+
3599
+ }
3600
+