pg 0.12.2-x86-mingw32 → 0.13.0-x86-mingw32

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