pg 0.12.2 → 0.13.0.pre298
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.hoerc +2 -0
- data/.tm_properties +12 -0
- data/ChangeLog +86 -6
- data/Contributors.rdoc +7 -0
- data/History.rdoc +29 -0
- data/LICENSE +12 -14
- data/Manifest.txt +15 -14
- data/{BSD → POSTGRES} +0 -0
- data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
- data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
- data/README.ja.rdoc +1 -1
- data/README.rdoc +39 -27
- data/Rakefile +1 -2
- data/ext/extconf.rb +9 -2
- data/ext/pg.c +232 -4297
- data/ext/pg.h +87 -23
- data/ext/pg_connection.c +3301 -0
- data/ext/pg_result.c +905 -0
- data/lib/pg.rb +26 -43
- data/lib/pg/connection.rb +58 -0
- data/lib/pg/constants.rb +11 -0
- data/lib/pg/exceptions.rb +11 -0
- data/lib/pg/result.rb +11 -0
- data/misc/openssl-pg-segfault.rb +1 -1
- data/sample/async_api.rb +16 -21
- data/sample/async_copyto.rb +1 -1
- data/sample/async_mixed.rb +56 -0
- data/sample/copyfrom.rb +1 -1
- data/sample/copyto.rb +1 -1
- data/sample/cursor.rb +1 -1
- data/sample/losample.rb +6 -6
- data/sample/notify_wait.rb +51 -22
- data/sample/test_binary_values.rb +4 -6
- data/spec/lib/helpers.rb +14 -10
- data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +227 -60
- data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
- data/spec/pg_spec.rb +22 -0
- metadata +44 -42
- metadata.gz.sig +0 -0
- data/GPL +0 -340
- data/ext/compat.c +0 -541
- data/ext/compat.h +0 -184
- data/sample/psql.rb +0 -1181
- data/sample/psqlHelp.rb +0 -158
- data/sample/test1.rb +0 -60
- data/sample/test2.rb +0 -44
- data/sample/test4.rb +0 -71
- data/spec/m17n_spec.rb +0 -170
data/ext/pg.c
CHANGED
@@ -1,3908 +1,122 @@
|
|
1
|
-
/************************************************
|
2
|
-
|
3
|
-
pg.c -
|
4
|
-
|
5
|
-
Author: matz
|
6
|
-
created at: Tue May 13 20:07:35 JST 1997
|
7
|
-
|
8
|
-
Author: ematsu
|
9
|
-
modified at: Wed Jan 20 16:41:51 1999
|
10
|
-
|
11
|
-
$Author: ged $
|
12
|
-
$Date: 2012/01/03 23:14:35 $
|
13
|
-
************************************************/
|
14
|
-
|
15
|
-
#include "pg.h"
|
16
|
-
#if defined(HAVE_RUBY_ENCODING_H) && HAVE_RUBY_ENCODING_H
|
17
|
-
# define M17N_SUPPORTED
|
18
|
-
#endif
|
19
|
-
|
20
|
-
#ifdef _WIN32
|
21
|
-
// for O_RDWR and O_BINARY
|
22
|
-
#include <fcntl.h>
|
23
|
-
#endif
|
24
|
-
|
25
|
-
#define rb_define_singleton_alias(klass,new,old) rb_define_alias(rb_singleton_class(klass),new,old)
|
26
|
-
|
27
|
-
static VALUE rb_cPGconn;
|
28
|
-
static VALUE rb_cPGresult;
|
29
|
-
static VALUE rb_ePGError;
|
30
|
-
|
31
|
-
static const char *VERSION = "0.12.2";
|
32
|
-
|
33
|
-
|
34
|
-
/* The following functions are part of libpq, but not
|
35
|
-
* available from ruby-pg, because they are deprecated,
|
36
|
-
* obsolete, or generally not useful:
|
37
|
-
*
|
38
|
-
* * PQfreemem -- unnecessary: copied to ruby object, then
|
39
|
-
* freed. Ruby object's memory is freed when
|
40
|
-
* it is garbage collected.
|
41
|
-
* * PQbinaryTuples -- better to use PQfformat
|
42
|
-
* * PQprint -- not very useful
|
43
|
-
* * PQsetdb -- not very useful
|
44
|
-
* * PQoidStatus -- deprecated, use PQoidValue
|
45
|
-
* * PQrequestCancel -- deprecated, use PQcancel
|
46
|
-
* * PQfn -- use a prepared statement instead
|
47
|
-
* * PQgetline -- deprecated, use PQgetCopyData
|
48
|
-
* * PQgetlineAsync -- deprecated, use PQgetCopyData
|
49
|
-
* * PQputline -- deprecated, use PQputCopyData
|
50
|
-
* * PQputnbytes -- deprecated, use PQputCopyData
|
51
|
-
* * PQendcopy -- deprecated, use PQputCopyEnd
|
52
|
-
*/
|
53
|
-
|
54
|
-
/***************************************************************************
|
55
|
-
* UTILITY FUNCTIONS
|
56
|
-
**************************************************************************/
|
57
|
-
|
58
|
-
static void free_pgconn( PGconn * );
|
59
|
-
static void pgresult_check( VALUE, VALUE );
|
60
|
-
|
61
|
-
static PGconn *get_pgconn( VALUE );
|
62
|
-
static VALUE pgconn_finish( VALUE );
|
63
|
-
static VALUE pgresult_clear( VALUE );
|
64
|
-
static VALUE pgresult_aref( VALUE, VALUE );
|
65
|
-
static VALUE make_column_result_array( VALUE, int );
|
66
|
-
|
67
|
-
#ifdef M17N_SUPPORTED
|
68
|
-
# define ASSOCIATE_INDEX( obj, index_holder ) rb_enc_associate_index((obj), enc_get_index((index_holder)))
|
69
|
-
static rb_encoding * pgconn_get_client_encoding_as_rb_encoding( PGconn * );
|
70
|
-
static const char * pgconn_get_rb_encoding_as_pg_encname( rb_encoding * );
|
71
|
-
static int enc_get_index( VALUE );
|
72
|
-
#else
|
73
|
-
# define ASSOCIATE_INDEX( obj, index_holder ) /* nothing */
|
74
|
-
#endif
|
75
|
-
|
76
|
-
static PQnoticeReceiver default_notice_receiver = NULL;
|
77
|
-
static PQnoticeProcessor default_notice_processor = NULL;
|
78
|
-
|
79
|
-
|
80
|
-
static void
|
81
|
-
free_pgconn(PGconn *conn)
|
82
|
-
{
|
83
|
-
if(conn != NULL)
|
84
|
-
PQfinish(conn);
|
85
|
-
}
|
86
|
-
|
87
|
-
static void
|
88
|
-
free_pgresult(PGresult *result)
|
89
|
-
{
|
90
|
-
if(result != NULL)
|
91
|
-
PQclear(result);
|
92
|
-
}
|
93
|
-
|
94
|
-
static PGconn*
|
95
|
-
get_pgconn(VALUE self)
|
96
|
-
{
|
97
|
-
PGconn *conn;
|
98
|
-
Data_Get_Struct(self, PGconn, conn);
|
99
|
-
if (conn == NULL) rb_raise(rb_ePGError, "not connected");
|
100
|
-
return conn;
|
101
|
-
}
|
102
|
-
|
103
|
-
static PGresult*
|
104
|
-
get_pgresult(VALUE self)
|
105
|
-
{
|
106
|
-
PGresult *result;
|
107
|
-
Data_Get_Struct(self, PGresult, result);
|
108
|
-
if (result == NULL) rb_raise(rb_ePGError, "result has been cleared");
|
109
|
-
return result;
|
110
|
-
}
|
111
|
-
|
112
|
-
#ifdef M17N_SUPPORTED
|
113
|
-
static VALUE
|
114
|
-
new_pgresult(PGresult *result, PGconn *conn)
|
115
|
-
{
|
116
|
-
VALUE val = Data_Wrap_Struct(rb_cPGresult, NULL, free_pgresult, result);
|
117
|
-
rb_encoding *enc = pgconn_get_client_encoding_as_rb_encoding(conn);
|
118
|
-
rb_enc_set_index(val, rb_enc_to_index(enc));
|
119
|
-
return val;
|
120
|
-
}
|
121
|
-
#else
|
122
|
-
static VALUE
|
123
|
-
new_pgresult(PGresult *result)
|
124
|
-
{
|
125
|
-
return Data_Wrap_Struct(rb_cPGresult, NULL, free_pgresult, result);
|
126
|
-
}
|
127
|
-
# define new_pgresult(result, conn) new_pgresult((result))
|
128
|
-
#endif
|
129
|
-
|
130
|
-
/*
|
131
|
-
* Raises appropriate exception if PGresult is
|
132
|
-
* in a bad state.
|
133
|
-
*/
|
134
|
-
static void
|
135
|
-
pgresult_check(VALUE rb_pgconn, VALUE rb_pgresult)
|
136
|
-
{
|
137
|
-
VALUE error, exception;
|
138
|
-
PGconn *conn = get_pgconn(rb_pgconn);
|
139
|
-
PGresult *result;
|
140
|
-
Data_Get_Struct(rb_pgresult, PGresult, result);
|
141
|
-
#ifdef M17N_SUPPORTED
|
142
|
-
rb_encoding *enc = pgconn_get_client_encoding_as_rb_encoding(conn);
|
143
|
-
#endif
|
144
|
-
|
145
|
-
if(result == NULL)
|
146
|
-
{
|
147
|
-
error = rb_str_new2( PQerrorMessage(conn) );
|
148
|
-
}
|
149
|
-
else
|
150
|
-
{
|
151
|
-
switch (PQresultStatus(result))
|
152
|
-
{
|
153
|
-
case PGRES_TUPLES_OK:
|
154
|
-
case PGRES_COPY_OUT:
|
155
|
-
case PGRES_COPY_IN:
|
156
|
-
case PGRES_EMPTY_QUERY:
|
157
|
-
case PGRES_COMMAND_OK:
|
158
|
-
return;
|
159
|
-
case PGRES_BAD_RESPONSE:
|
160
|
-
case PGRES_FATAL_ERROR:
|
161
|
-
case PGRES_NONFATAL_ERROR:
|
162
|
-
error = rb_str_new2( PQresultErrorMessage(result) );
|
163
|
-
break;
|
164
|
-
default:
|
165
|
-
error = rb_str_new2( "internal error : unknown result status." );
|
166
|
-
}
|
167
|
-
}
|
168
|
-
|
169
|
-
#ifdef M17N_SUPPORTED
|
170
|
-
rb_enc_set_index( error, rb_enc_to_index(enc) );
|
171
|
-
#endif
|
172
|
-
exception = rb_exc_new3( rb_ePGError, error );
|
173
|
-
rb_iv_set( exception, "@connection", rb_pgconn );
|
174
|
-
rb_iv_set( exception, "@result", rb_pgresult );
|
175
|
-
rb_exc_raise( exception );
|
176
|
-
|
177
|
-
return;
|
178
|
-
}
|
179
|
-
|
180
|
-
static void
|
181
|
-
notice_receiver_proxy(void *arg, const PGresult *result)
|
182
|
-
{
|
183
|
-
VALUE proc;
|
184
|
-
VALUE self = (VALUE)arg;
|
185
|
-
|
186
|
-
if ((proc = rb_iv_get(self, "@notice_receiver")) != Qnil) {
|
187
|
-
rb_funcall(proc, rb_intern("call"), 1,
|
188
|
-
Data_Wrap_Struct(rb_cPGresult, NULL, NULL, (PGresult*)result));
|
189
|
-
}
|
190
|
-
return;
|
191
|
-
}
|
192
|
-
|
193
|
-
static void
|
194
|
-
notice_processor_proxy(void *arg, const char *message)
|
195
|
-
{
|
196
|
-
VALUE proc;
|
197
|
-
VALUE self = (VALUE)arg;
|
198
|
-
|
199
|
-
if ((proc = rb_iv_get(self, "@notice_processor")) != Qnil) {
|
200
|
-
rb_funcall(proc, rb_intern("call"), 1, rb_tainted_str_new2(message));
|
201
|
-
}
|
202
|
-
return;
|
203
|
-
}
|
204
|
-
|
205
|
-
|
206
|
-
/********************************************************************
|
207
|
-
*
|
208
|
-
* Document-class: PGError
|
209
|
-
*
|
210
|
-
* This is the exception class raised when an error is returned from
|
211
|
-
* a libpq API call.
|
212
|
-
*
|
213
|
-
* The attributes +connection+ and +result+ are set to the connection
|
214
|
-
* object and result set object, respectively.
|
215
|
-
*
|
216
|
-
* If the connection object or result set object is not available from
|
217
|
-
* the context in which the error was encountered, it is +nil+.
|
218
|
-
*/
|
219
|
-
|
220
|
-
/********************************************************************
|
221
|
-
*
|
222
|
-
* Document-class: PGconn
|
223
|
-
*
|
224
|
-
* The class to access PostgreSQL RDBMS, based on the libpq interface,
|
225
|
-
* provides convenient OO methods to interact with PostgreSQL.
|
226
|
-
*
|
227
|
-
* For example, to send query to the database on the localhost:
|
228
|
-
* require 'pg'
|
229
|
-
* conn = PGconn.open(:dbname => 'test')
|
230
|
-
* res = conn.exec('SELECT $1 AS a, $2 AS b, $3 AS c',[1, 2, nil])
|
231
|
-
* # Equivalent to:
|
232
|
-
* # res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
233
|
-
*
|
234
|
-
* See the PGresult class for information on working with the results of a query.
|
235
|
-
*
|
236
|
-
*/
|
237
|
-
|
238
|
-
static VALUE
|
239
|
-
pgconn_alloc(VALUE klass)
|
240
|
-
{
|
241
|
-
return Data_Wrap_Struct(klass, NULL, free_pgconn, NULL);
|
242
|
-
}
|
243
|
-
|
244
|
-
/**************************************************************************
|
245
|
-
* PGconn SINGLETON METHODS
|
246
|
-
**************************************************************************/
|
247
|
-
|
248
|
-
/*
|
249
|
-
* Document-method: new
|
250
|
-
*
|
251
|
-
* call-seq:
|
252
|
-
* PGconn.new -> PGconn
|
253
|
-
* PGconn.new(connection_hash) -> PGconn
|
254
|
-
* PGconn.new(connection_string) -> PGconn
|
255
|
-
* PGconn.new(host, port, options, tty, dbname, user, password) -> PGconn
|
256
|
-
*
|
257
|
-
* Create a connection to the specified server.
|
258
|
-
*
|
259
|
-
* [+host+]
|
260
|
-
* server hostname
|
261
|
-
* [+hostaddr+]
|
262
|
-
* server address (avoids hostname lookup, overrides +host+)
|
263
|
-
* [+port+]
|
264
|
-
* server port number
|
265
|
-
* [+dbname+]
|
266
|
-
* connecting database name
|
267
|
-
* [+user+]
|
268
|
-
* login user name
|
269
|
-
* [+password+]
|
270
|
-
* login password
|
271
|
-
* [+connect_timeout+]
|
272
|
-
* maximum time to wait for connection to succeed
|
273
|
-
* [+options+]
|
274
|
-
* backend options
|
275
|
-
* [+tty+]
|
276
|
-
* (ignored in newer versions of PostgreSQL)
|
277
|
-
* [+sslmode+]
|
278
|
-
* (disable|allow|prefer|require)
|
279
|
-
* [+krbsrvname+]
|
280
|
-
* kerberos service name
|
281
|
-
* [+gsslib+]
|
282
|
-
* GSS library to use for GSSAPI authentication
|
283
|
-
* [+service+]
|
284
|
-
* service name to use for additional parameters
|
285
|
-
*
|
286
|
-
* Examples:
|
287
|
-
*
|
288
|
-
* # Connect using all defaults
|
289
|
-
* PGconn.connect
|
290
|
-
*
|
291
|
-
* # As a Hash
|
292
|
-
* PGconn.connect( :dbname => 'test', :port => 5432 )
|
293
|
-
*
|
294
|
-
* # As a String
|
295
|
-
* PGconn.connect( "dbname=test port=5432" )
|
296
|
-
*
|
297
|
-
* # As an Array
|
298
|
-
* PGconn.connect( nil, 5432, nil, nil, 'test', nil, nil )
|
299
|
-
*
|
300
|
-
* If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
|
301
|
-
* connection will have its +client_encoding+ set accordingly.
|
302
|
-
*
|
303
|
-
* Raises a PGError if the connection fails.
|
304
|
-
*/
|
305
|
-
static VALUE
|
306
|
-
pgconn_init(int argc, VALUE *argv, VALUE self)
|
307
|
-
{
|
308
|
-
PGconn *conn = NULL;
|
309
|
-
VALUE conninfo;
|
310
|
-
VALUE error;
|
311
|
-
#ifdef M17N_SUPPORTED
|
312
|
-
rb_encoding *enc;
|
313
|
-
const char *encname;
|
314
|
-
#endif
|
315
|
-
|
316
|
-
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
317
|
-
conn = PQconnectdb(StringValuePtr(conninfo));
|
318
|
-
|
319
|
-
if(conn == NULL)
|
320
|
-
rb_raise(rb_ePGError, "PQconnectStart() unable to allocate structure");
|
321
|
-
|
322
|
-
Check_Type(self, T_DATA);
|
323
|
-
DATA_PTR(self) = conn;
|
324
|
-
|
325
|
-
if (PQstatus(conn) == CONNECTION_BAD) {
|
326
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
327
|
-
rb_iv_set(error, "@connection", self);
|
328
|
-
rb_exc_raise(error);
|
329
|
-
}
|
330
|
-
|
331
|
-
#ifdef M17N_SUPPORTED
|
332
|
-
/* If Ruby has its Encoding.default_internal set, set PostgreSQL's client_encoding
|
333
|
-
* to match */
|
334
|
-
if (( enc = rb_default_internal_encoding() )) {
|
335
|
-
encname = pgconn_get_rb_encoding_as_pg_encname( enc );
|
336
|
-
if ( PQsetClientEncoding(conn, encname) != 0 )
|
337
|
-
rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
|
338
|
-
encname, PQerrorMessage(conn) );
|
339
|
-
}
|
340
|
-
#endif
|
341
|
-
|
342
|
-
if (rb_block_given_p()) {
|
343
|
-
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
344
|
-
}
|
345
|
-
return self;
|
346
|
-
}
|
347
|
-
|
348
|
-
/*
|
349
|
-
* call-seq:
|
350
|
-
* PGconn.connect_start(connection_hash) -> PGconn
|
351
|
-
* PGconn.connect_start(connection_string) -> PGconn
|
352
|
-
* PGconn.connect_start(host, port, options, tty, dbname, login, password) -> PGconn
|
353
|
-
*
|
354
|
-
* This is an asynchronous version of PGconn.connect().
|
355
|
-
*
|
356
|
-
* Use PGconn#connect_poll to poll the status of the connection.
|
357
|
-
*
|
358
|
-
* NOTE: this does *not* set the connection's +client_encoding+ for you if
|
359
|
-
* Encoding.default_internal is set. To set it after the connection is established,
|
360
|
-
* call PGconn#internal_encoding=. You can also set it automatically by setting
|
361
|
-
* ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
|
362
|
-
*
|
363
|
-
*/
|
364
|
-
static VALUE
|
365
|
-
pgconn_s_connect_start(int argc, VALUE *argv, VALUE self)
|
366
|
-
{
|
367
|
-
PGconn *conn = NULL;
|
368
|
-
VALUE rb_conn;
|
369
|
-
VALUE conninfo;
|
370
|
-
VALUE error;
|
371
|
-
|
372
|
-
/*
|
373
|
-
* PGconn.connect_start must act as both alloc() and initialize()
|
374
|
-
* because it is not invoked by calling new().
|
375
|
-
*/
|
376
|
-
rb_conn = pgconn_alloc(rb_cPGconn);
|
377
|
-
|
378
|
-
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
379
|
-
conn = PQconnectStart(StringValuePtr(conninfo));
|
380
|
-
|
381
|
-
if(conn == NULL)
|
382
|
-
rb_raise(rb_ePGError, "PQconnectStart() unable to allocate structure");
|
383
|
-
if (PQstatus(conn) == CONNECTION_BAD) {
|
384
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
385
|
-
rb_iv_set(error, "@connection", self);
|
386
|
-
rb_exc_raise(error);
|
387
|
-
}
|
388
|
-
|
389
|
-
Check_Type(rb_conn, T_DATA);
|
390
|
-
DATA_PTR(rb_conn) = conn;
|
391
|
-
|
392
|
-
if (rb_block_given_p()) {
|
393
|
-
return rb_ensure(rb_yield, self, pgconn_finish, self);
|
394
|
-
}
|
395
|
-
return rb_conn;
|
396
|
-
}
|
397
|
-
|
398
|
-
/*
|
399
|
-
* call-seq:
|
400
|
-
* PGconn.conndefaults() -> Array
|
401
|
-
*
|
402
|
-
* Returns an array of hashes. Each hash has the keys:
|
403
|
-
* [+:keyword+]
|
404
|
-
* the name of the option
|
405
|
-
* [+:envvar+]
|
406
|
-
* the environment variable to fall back to
|
407
|
-
* [+:compiled+]
|
408
|
-
* the compiled in option as a secondary fallback
|
409
|
-
* [+:val+]
|
410
|
-
* the option's current value, or +nil+ if not known
|
411
|
-
* [+:label+]
|
412
|
-
* the label for the field
|
413
|
-
* [+:dispchar+]
|
414
|
-
* "" for normal, "D" for debug, and "*" for password
|
415
|
-
* [+:dispsize+]
|
416
|
-
* field size
|
417
|
-
*/
|
418
|
-
static VALUE
|
419
|
-
pgconn_s_conndefaults(VALUE self)
|
420
|
-
{
|
421
|
-
PQconninfoOption *options = PQconndefaults();
|
422
|
-
VALUE ary = rb_ary_new();
|
423
|
-
VALUE hash;
|
424
|
-
int i = 0;
|
425
|
-
|
426
|
-
for(i = 0; options[i].keyword != NULL; i++) {
|
427
|
-
hash = rb_hash_new();
|
428
|
-
if(options[i].keyword)
|
429
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("keyword")),
|
430
|
-
rb_str_new2(options[i].keyword));
|
431
|
-
if(options[i].envvar)
|
432
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("envvar")),
|
433
|
-
rb_str_new2(options[i].envvar));
|
434
|
-
if(options[i].compiled)
|
435
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("compiled")),
|
436
|
-
rb_str_new2(options[i].compiled));
|
437
|
-
if(options[i].val)
|
438
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("val")),
|
439
|
-
rb_str_new2(options[i].val));
|
440
|
-
if(options[i].label)
|
441
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("label")),
|
442
|
-
rb_str_new2(options[i].label));
|
443
|
-
if(options[i].dispchar)
|
444
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("dispchar")),
|
445
|
-
rb_str_new2(options[i].dispchar));
|
446
|
-
rb_hash_aset(hash, ID2SYM(rb_intern("dispsize")),
|
447
|
-
INT2NUM(options[i].dispsize));
|
448
|
-
rb_ary_push(ary, hash);
|
449
|
-
}
|
450
|
-
PQconninfoFree(options);
|
451
|
-
return ary;
|
452
|
-
}
|
453
|
-
|
454
|
-
|
455
|
-
/*
|
456
|
-
* call-seq:
|
457
|
-
* PGconn.encrypt_password( password, username ) -> String
|
458
|
-
*
|
459
|
-
* This function is intended to be used by client applications that
|
460
|
-
* send commands like: +ALTER USER joe PASSWORD 'pwd'+.
|
461
|
-
* The arguments are the cleartext password, and the SQL name
|
462
|
-
* of the user it is for.
|
463
|
-
*
|
464
|
-
* Return value is the encrypted password.
|
465
|
-
*/
|
466
|
-
static VALUE
|
467
|
-
pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
468
|
-
{
|
469
|
-
char *encrypted = NULL;
|
470
|
-
VALUE rval = Qnil;
|
471
|
-
|
472
|
-
Check_Type(password, T_STRING);
|
473
|
-
Check_Type(username, T_STRING);
|
474
|
-
|
475
|
-
encrypted = PQencryptPassword(StringValuePtr(password), StringValuePtr(username));
|
476
|
-
rval = rb_str_new2( encrypted );
|
477
|
-
PQfreemem( encrypted );
|
478
|
-
|
479
|
-
OBJ_INFECT( rval, password );
|
480
|
-
OBJ_INFECT( rval, username );
|
481
|
-
|
482
|
-
return rval;
|
483
|
-
}
|
484
|
-
|
485
|
-
|
486
|
-
/*
|
487
|
-
* call-seq:
|
488
|
-
* PGconn.isthreadsafe() -> Boolean
|
489
|
-
*
|
490
|
-
* Returns +true+ if libpq is thread safe, +false+ otherwise.
|
491
|
-
*/
|
492
|
-
static VALUE
|
493
|
-
pgconn_s_isthreadsafe(VALUE self)
|
494
|
-
{
|
495
|
-
return PQisthreadsafe() ? Qtrue : Qfalse;
|
496
|
-
}
|
497
|
-
|
498
|
-
/**************************************************************************
|
499
|
-
* PGconn INSTANCE METHODS
|
500
|
-
**************************************************************************/
|
501
|
-
|
502
|
-
/*
|
503
|
-
* call-seq:
|
504
|
-
* conn.connect_poll() -> Fixnum
|
505
|
-
*
|
506
|
-
* Returns one of:
|
507
|
-
* [+PGRES_POLLING_READING+]
|
508
|
-
* wait until the socket is ready to read
|
509
|
-
* [+PGRES_POLLING_WRITING+]
|
510
|
-
* wait until the socket is ready to write
|
511
|
-
* [+PGRES_POLLING_FAILED+]
|
512
|
-
* the asynchronous connection has failed
|
513
|
-
* [+PGRES_POLLING_OK+]
|
514
|
-
* the asynchronous connection is ready
|
515
|
-
*
|
516
|
-
* Example:
|
517
|
-
* conn = PGconn.connect_start("dbname=mydatabase")
|
518
|
-
* socket = IO.for_fd(conn.socket)
|
519
|
-
* status = conn.connect_poll
|
520
|
-
* while(status != PGconn::PGRES_POLLING_OK) do
|
521
|
-
* # do some work while waiting for the connection to complete
|
522
|
-
* if(status == PGconn::PGRES_POLLING_READING)
|
523
|
-
* if(not select([socket], [], [], 10.0))
|
524
|
-
* raise "Asynchronous connection timed out!"
|
525
|
-
* end
|
526
|
-
* elsif(status == PGconn::PGRES_POLLING_WRITING)
|
527
|
-
* if(not select([], [socket], [], 10.0))
|
528
|
-
* raise "Asynchronous connection timed out!"
|
529
|
-
* end
|
530
|
-
* end
|
531
|
-
* status = conn.connect_poll
|
532
|
-
* end
|
533
|
-
* # now conn.status == CONNECTION_OK, and connection
|
534
|
-
* # is ready.
|
535
|
-
*/
|
536
|
-
static VALUE
|
537
|
-
pgconn_connect_poll(VALUE self)
|
538
|
-
{
|
539
|
-
PostgresPollingStatusType status;
|
540
|
-
status = PQconnectPoll(get_pgconn(self));
|
541
|
-
return INT2FIX((int)status);
|
542
|
-
}
|
543
|
-
|
544
|
-
/*
|
545
|
-
* call-seq:
|
546
|
-
* conn.finish()
|
547
|
-
*
|
548
|
-
* Closes the backend connection.
|
549
|
-
*/
|
550
|
-
static VALUE
|
551
|
-
pgconn_finish(VALUE self)
|
552
|
-
{
|
553
|
-
PQfinish(get_pgconn(self));
|
554
|
-
DATA_PTR(self) = NULL;
|
555
|
-
return Qnil;
|
556
|
-
}
|
557
|
-
|
558
|
-
/*
|
559
|
-
* call-seq:
|
560
|
-
* conn.reset()
|
561
|
-
*
|
562
|
-
* Resets the backend connection. This method closes the
|
563
|
-
* backend connection and tries to re-connect.
|
564
|
-
*/
|
565
|
-
static VALUE
|
566
|
-
pgconn_reset(VALUE self)
|
567
|
-
{
|
568
|
-
PQreset(get_pgconn(self));
|
569
|
-
return self;
|
570
|
-
}
|
571
|
-
|
572
|
-
/*
|
573
|
-
* call-seq:
|
574
|
-
* conn.reset_start() -> nil
|
575
|
-
*
|
576
|
-
* Initiate a connection reset in a nonblocking manner.
|
577
|
-
* This will close the current connection and attempt to
|
578
|
-
* reconnect using the same connection parameters.
|
579
|
-
* Use PGconn#reset_poll to check the status of the
|
580
|
-
* connection reset.
|
581
|
-
*/
|
582
|
-
static VALUE
|
583
|
-
pgconn_reset_start(VALUE self)
|
584
|
-
{
|
585
|
-
if(PQresetStart(get_pgconn(self)) == 0)
|
586
|
-
rb_raise(rb_ePGError, "reset has failed");
|
587
|
-
return Qnil;
|
588
|
-
}
|
589
|
-
|
590
|
-
/*
|
591
|
-
* call-seq:
|
592
|
-
* conn.reset_poll -> Fixnum
|
593
|
-
*
|
594
|
-
* Checks the status of a connection reset operation.
|
595
|
-
* See PGconn#connect_start and PGconn#connect_poll for
|
596
|
-
* usage information and return values.
|
597
|
-
*/
|
598
|
-
static VALUE
|
599
|
-
pgconn_reset_poll(VALUE self)
|
600
|
-
{
|
601
|
-
PostgresPollingStatusType status;
|
602
|
-
status = PQresetPoll(get_pgconn(self));
|
603
|
-
return INT2FIX((int)status);
|
604
|
-
}
|
605
|
-
|
606
|
-
/*
|
607
|
-
* call-seq:
|
608
|
-
* conn.db()
|
609
|
-
*
|
610
|
-
* Returns the connected database name.
|
611
|
-
*/
|
612
|
-
static VALUE
|
613
|
-
pgconn_db(VALUE self)
|
614
|
-
{
|
615
|
-
char *db = PQdb(get_pgconn(self));
|
616
|
-
if (!db) return Qnil;
|
617
|
-
return rb_tainted_str_new2(db);
|
618
|
-
}
|
619
|
-
|
620
|
-
/*
|
621
|
-
* call-seq:
|
622
|
-
* conn.user()
|
623
|
-
*
|
624
|
-
* Returns the authenticated user name.
|
625
|
-
*/
|
626
|
-
static VALUE
|
627
|
-
pgconn_user(VALUE self)
|
628
|
-
{
|
629
|
-
char *user = PQuser(get_pgconn(self));
|
630
|
-
if (!user) return Qnil;
|
631
|
-
return rb_tainted_str_new2(user);
|
632
|
-
}
|
633
|
-
|
634
|
-
/*
|
635
|
-
* call-seq:
|
636
|
-
* conn.pass()
|
637
|
-
*
|
638
|
-
* Returns the authenticated user name.
|
639
|
-
*/
|
640
|
-
static VALUE
|
641
|
-
pgconn_pass(VALUE self)
|
642
|
-
{
|
643
|
-
char *user = PQpass(get_pgconn(self));
|
644
|
-
if (!user) return Qnil;
|
645
|
-
return rb_tainted_str_new2(user);
|
646
|
-
}
|
647
|
-
|
648
|
-
/*
|
649
|
-
* call-seq:
|
650
|
-
* conn.host()
|
651
|
-
*
|
652
|
-
* Returns the connected server name.
|
653
|
-
*/
|
654
|
-
static VALUE
|
655
|
-
pgconn_host(VALUE self)
|
656
|
-
{
|
657
|
-
char *host = PQhost(get_pgconn(self));
|
658
|
-
if (!host) return Qnil;
|
659
|
-
return rb_tainted_str_new2(host);
|
660
|
-
}
|
661
|
-
|
662
|
-
/*
|
663
|
-
* call-seq:
|
664
|
-
* conn.port()
|
665
|
-
*
|
666
|
-
* Returns the connected server port number.
|
667
|
-
*/
|
668
|
-
static VALUE
|
669
|
-
pgconn_port(VALUE self)
|
670
|
-
{
|
671
|
-
char* port = PQport(get_pgconn(self));
|
672
|
-
return INT2NUM(atol(port));
|
673
|
-
}
|
674
|
-
|
675
|
-
/*
|
676
|
-
* call-seq:
|
677
|
-
* conn.tty()
|
678
|
-
*
|
679
|
-
* Returns the connected pgtty. (Obsolete)
|
680
|
-
*/
|
681
|
-
static VALUE
|
682
|
-
pgconn_tty(VALUE self)
|
683
|
-
{
|
684
|
-
char *tty = PQtty(get_pgconn(self));
|
685
|
-
if (!tty) return Qnil;
|
686
|
-
return rb_tainted_str_new2(tty);
|
687
|
-
}
|
688
|
-
|
689
|
-
/*
|
690
|
-
* call-seq:
|
691
|
-
* conn.options()
|
692
|
-
*
|
693
|
-
* Returns backend option string.
|
694
|
-
*/
|
695
|
-
static VALUE
|
696
|
-
pgconn_options(VALUE self)
|
697
|
-
{
|
698
|
-
char *options = PQoptions(get_pgconn(self));
|
699
|
-
if (!options) return Qnil;
|
700
|
-
return rb_tainted_str_new2(options);
|
701
|
-
}
|
702
|
-
|
703
|
-
/*
|
704
|
-
* call-seq:
|
705
|
-
* conn.status()
|
706
|
-
*
|
707
|
-
* Returns status of connection : CONNECTION_OK or CONNECTION_BAD
|
708
|
-
*/
|
709
|
-
static VALUE
|
710
|
-
pgconn_status(VALUE self)
|
711
|
-
{
|
712
|
-
return INT2NUM(PQstatus(get_pgconn(self)));
|
713
|
-
}
|
714
|
-
|
715
|
-
/*
|
716
|
-
* call-seq:
|
717
|
-
* conn.transaction_status()
|
718
|
-
*
|
719
|
-
* returns one of the following statuses:
|
720
|
-
* PQTRANS_IDLE = 0 (connection idle)
|
721
|
-
* PQTRANS_ACTIVE = 1 (command in progress)
|
722
|
-
* PQTRANS_INTRANS = 2 (idle, within transaction block)
|
723
|
-
* PQTRANS_INERROR = 3 (idle, within failed transaction)
|
724
|
-
* PQTRANS_UNKNOWN = 4 (cannot determine status)
|
725
|
-
*/
|
726
|
-
static VALUE
|
727
|
-
pgconn_transaction_status(VALUE self)
|
728
|
-
{
|
729
|
-
return INT2NUM(PQtransactionStatus(get_pgconn(self)));
|
730
|
-
}
|
731
|
-
|
732
|
-
/*
|
733
|
-
* call-seq:
|
734
|
-
* conn.parameter_status( param_name ) -> String
|
735
|
-
*
|
736
|
-
* Returns the setting of parameter _param_name_, where
|
737
|
-
* _param_name_ is one of
|
738
|
-
* * +server_version+
|
739
|
-
* * +server_encoding+
|
740
|
-
* * +client_encoding+
|
741
|
-
* * +is_superuser+
|
742
|
-
* * +session_authorization+
|
743
|
-
* * +DateStyle+
|
744
|
-
* * +TimeZone+
|
745
|
-
* * +integer_datetimes+
|
746
|
-
* * +standard_conforming_strings+
|
747
|
-
*
|
748
|
-
* Returns nil if the value of the parameter is not known.
|
749
|
-
*/
|
750
|
-
static VALUE
|
751
|
-
pgconn_parameter_status(VALUE self, VALUE param_name)
|
752
|
-
{
|
753
|
-
const char *ret = PQparameterStatus(get_pgconn(self),
|
754
|
-
StringValuePtr(param_name));
|
755
|
-
if(ret == NULL)
|
756
|
-
return Qnil;
|
757
|
-
else
|
758
|
-
return rb_tainted_str_new2(ret);
|
759
|
-
}
|
760
|
-
|
761
|
-
/*
|
762
|
-
* call-seq:
|
763
|
-
* conn.protocol_version -> Integer
|
764
|
-
*
|
765
|
-
* The 3.0 protocol will normally be used when communicating with PostgreSQL 7.4
|
766
|
-
* or later servers; pre-7.4 servers support only protocol 2.0. (Protocol 1.0 is
|
767
|
-
* obsolete and not supported by libpq.)
|
768
|
-
*/
|
769
|
-
static VALUE
|
770
|
-
pgconn_protocol_version(VALUE self)
|
771
|
-
{
|
772
|
-
return INT2NUM(PQprotocolVersion(get_pgconn(self)));
|
773
|
-
}
|
774
|
-
|
775
|
-
/*
|
776
|
-
* call-seq:
|
777
|
-
* conn.server_version -> Integer
|
778
|
-
*
|
779
|
-
* The number is formed by converting the major, minor, and revision
|
780
|
-
* numbers into two-decimal-digit numbers and appending them together.
|
781
|
-
* For example, version 7.4.2 will be returned as 70402, and version
|
782
|
-
* 8.1 will be returned as 80100 (leading zeroes are not shown). Zero
|
783
|
-
* is returned if the connection is bad.
|
784
|
-
*
|
785
|
-
*/
|
786
|
-
static VALUE
|
787
|
-
pgconn_server_version(VALUE self)
|
788
|
-
{
|
789
|
-
return INT2NUM(PQserverVersion(get_pgconn(self)));
|
790
|
-
}
|
791
|
-
|
792
|
-
/*
|
793
|
-
* call-seq:
|
794
|
-
* conn.error_message -> String
|
795
|
-
*
|
796
|
-
* Returns the error message about connection.
|
797
|
-
*/
|
798
|
-
static VALUE
|
799
|
-
pgconn_error_message(VALUE self)
|
800
|
-
{
|
801
|
-
char *error = PQerrorMessage(get_pgconn(self));
|
802
|
-
if (!error) return Qnil;
|
803
|
-
return rb_tainted_str_new2(error);
|
804
|
-
}
|
805
|
-
|
806
|
-
/*
|
807
|
-
* call-seq:
|
808
|
-
* conn.socket() -> Fixnum
|
809
|
-
*
|
810
|
-
* Returns the socket's file descriptor for this connection.
|
811
|
-
*/
|
812
|
-
static VALUE
|
813
|
-
pgconn_socket(VALUE self)
|
814
|
-
{
|
815
|
-
int sd;
|
816
|
-
if( (sd = PQsocket(get_pgconn(self))) < 0)
|
817
|
-
rb_raise(rb_ePGError, "Can't get socket descriptor");
|
818
|
-
return INT2NUM(sd);
|
819
|
-
}
|
820
|
-
|
821
|
-
|
822
|
-
/*
|
823
|
-
* call-seq:
|
824
|
-
* conn.backend_pid() -> Fixnum
|
825
|
-
*
|
826
|
-
* Returns the process ID of the backend server
|
827
|
-
* process for this connection.
|
828
|
-
* Note that this is a PID on database server host.
|
829
|
-
*/
|
830
|
-
static VALUE
|
831
|
-
pgconn_backend_pid(VALUE self)
|
832
|
-
{
|
833
|
-
return INT2NUM(PQbackendPID(get_pgconn(self)));
|
834
|
-
}
|
835
|
-
|
836
|
-
/*
|
837
|
-
* call-seq:
|
838
|
-
* conn.connection_needs_password() -> Boolean
|
839
|
-
*
|
840
|
-
* Returns +true+ if the authentication method required a
|
841
|
-
* password, but none was available. +false+ otherwise.
|
842
|
-
*/
|
843
|
-
static VALUE
|
844
|
-
pgconn_connection_needs_password(VALUE self)
|
845
|
-
{
|
846
|
-
return PQconnectionNeedsPassword(get_pgconn(self)) ? Qtrue : Qfalse;
|
847
|
-
}
|
848
|
-
|
849
|
-
/*
|
850
|
-
* call-seq:
|
851
|
-
* conn.connection_used_password() -> Boolean
|
852
|
-
*
|
853
|
-
* Returns +true+ if the authentication method used
|
854
|
-
* a caller-supplied password, +false+ otherwise.
|
855
|
-
*/
|
856
|
-
static VALUE
|
857
|
-
pgconn_connection_used_password(VALUE self)
|
858
|
-
{
|
859
|
-
return PQconnectionUsedPassword(get_pgconn(self)) ? Qtrue : Qfalse;
|
860
|
-
}
|
861
|
-
|
862
|
-
|
863
|
-
//TODO get_ssl
|
864
|
-
|
865
|
-
|
866
|
-
/*
|
867
|
-
* call-seq:
|
868
|
-
* conn.exec(sql [, params, result_format ] ) -> PGresult
|
869
|
-
* conn.exec(sql [, params, result_format ] ) {|pg_result| block }
|
870
|
-
*
|
871
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL.
|
872
|
-
* Returns a PGresult instance on success.
|
873
|
-
* On failure, it raises a PGError exception.
|
874
|
-
*
|
875
|
-
* +params+ is an optional array of the bind parameters for the SQL query.
|
876
|
-
* Each element of the +params+ array may be either:
|
877
|
-
* a hash of the form:
|
878
|
-
* {:value => String (value of bind parameter)
|
879
|
-
* :type => Fixnum (oid of type of bind parameter)
|
880
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
881
|
-
* }
|
882
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
883
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
884
|
-
*
|
885
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
886
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
887
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
888
|
-
*
|
889
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
890
|
-
* Instead of specifying type oids, it's recommended to simply add
|
891
|
-
* explicit casts in the query to ensure that the right type is used.
|
892
|
-
*
|
893
|
-
* For example: "SELECT $1::int"
|
894
|
-
*
|
895
|
-
* The optional +result_format+ should be 0 for text results, 1
|
896
|
-
* for binary.
|
897
|
-
*
|
898
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
899
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
900
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
901
|
-
*/
|
902
|
-
static VALUE
|
903
|
-
pgconn_exec(int argc, VALUE *argv, VALUE self)
|
904
|
-
{
|
905
|
-
PGconn *conn = get_pgconn(self);
|
906
|
-
PGresult *result = NULL;
|
907
|
-
VALUE rb_pgresult;
|
908
|
-
VALUE command, params, in_res_fmt;
|
909
|
-
VALUE param, param_type, param_value, param_format;
|
910
|
-
VALUE param_value_tmp;
|
911
|
-
VALUE sym_type, sym_value, sym_format;
|
912
|
-
VALUE gc_array;
|
913
|
-
int i=0;
|
914
|
-
int nParams;
|
915
|
-
Oid *paramTypes;
|
916
|
-
char ** paramValues;
|
917
|
-
int *paramLengths;
|
918
|
-
int *paramFormats;
|
919
|
-
int resultFormat;
|
920
|
-
|
921
|
-
rb_scan_args(argc, argv, "12", &command, ¶ms, &in_res_fmt);
|
922
|
-
|
923
|
-
Check_Type(command, T_STRING);
|
924
|
-
|
925
|
-
/* If called with no parameters, use PQexec */
|
926
|
-
if(NIL_P(params)) {
|
927
|
-
result = PQexec(conn, StringValuePtr(command));
|
928
|
-
rb_pgresult = new_pgresult(result, conn);
|
929
|
-
pgresult_check(self, rb_pgresult);
|
930
|
-
if (rb_block_given_p()) {
|
931
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
932
|
-
pgresult_clear, rb_pgresult);
|
933
|
-
}
|
934
|
-
return rb_pgresult;
|
935
|
-
}
|
936
|
-
|
937
|
-
/* If called with parameters, and optionally result_format,
|
938
|
-
* use PQexecParams
|
939
|
-
*/
|
940
|
-
Check_Type(params, T_ARRAY);
|
941
|
-
|
942
|
-
if(NIL_P(in_res_fmt)) {
|
943
|
-
resultFormat = 0;
|
944
|
-
}
|
945
|
-
else {
|
946
|
-
resultFormat = NUM2INT(in_res_fmt);
|
947
|
-
}
|
948
|
-
|
949
|
-
gc_array = rb_ary_new();
|
950
|
-
rb_gc_register_address(&gc_array);
|
951
|
-
sym_type = ID2SYM(rb_intern("type"));
|
952
|
-
sym_value = ID2SYM(rb_intern("value"));
|
953
|
-
sym_format = ID2SYM(rb_intern("format"));
|
954
|
-
nParams = RARRAY_LEN(params);
|
955
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
956
|
-
paramValues = ALLOC_N(char *, nParams);
|
957
|
-
paramLengths = ALLOC_N(int, nParams);
|
958
|
-
paramFormats = ALLOC_N(int, nParams);
|
959
|
-
for(i = 0; i < nParams; i++) {
|
960
|
-
param = rb_ary_entry(params, i);
|
961
|
-
if (TYPE(param) == T_HASH) {
|
962
|
-
param_type = rb_hash_aref(param, sym_type);
|
963
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
964
|
-
if(param_value_tmp == Qnil)
|
965
|
-
param_value = param_value_tmp;
|
966
|
-
else
|
967
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
968
|
-
param_format = rb_hash_aref(param, sym_format);
|
969
|
-
}
|
970
|
-
else {
|
971
|
-
param_type = Qnil;
|
972
|
-
if(param == Qnil)
|
973
|
-
param_value = param;
|
974
|
-
else
|
975
|
-
param_value = rb_obj_as_string(param);
|
976
|
-
param_format = Qnil;
|
977
|
-
}
|
978
|
-
|
979
|
-
if(param_type == Qnil)
|
980
|
-
paramTypes[i] = 0;
|
981
|
-
else
|
982
|
-
paramTypes[i] = NUM2INT(param_type);
|
983
|
-
|
984
|
-
if(param_value == Qnil) {
|
985
|
-
paramValues[i] = NULL;
|
986
|
-
paramLengths[i] = 0;
|
987
|
-
}
|
988
|
-
else {
|
989
|
-
Check_Type(param_value, T_STRING);
|
990
|
-
/* make sure param_value doesn't get freed by the GC */
|
991
|
-
rb_ary_push(gc_array, param_value);
|
992
|
-
paramValues[i] = StringValuePtr(param_value);
|
993
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
994
|
-
}
|
995
|
-
|
996
|
-
if(param_format == Qnil)
|
997
|
-
paramFormats[i] = 0;
|
998
|
-
else
|
999
|
-
paramFormats[i] = NUM2INT(param_format);
|
1000
|
-
}
|
1001
|
-
|
1002
|
-
result = PQexecParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1003
|
-
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1004
|
-
|
1005
|
-
rb_gc_unregister_address(&gc_array);
|
1006
|
-
|
1007
|
-
xfree(paramTypes);
|
1008
|
-
xfree(paramValues);
|
1009
|
-
xfree(paramLengths);
|
1010
|
-
xfree(paramFormats);
|
1011
|
-
|
1012
|
-
rb_pgresult = new_pgresult(result, conn);
|
1013
|
-
pgresult_check(self, rb_pgresult);
|
1014
|
-
if (rb_block_given_p()) {
|
1015
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1016
|
-
pgresult_clear, rb_pgresult);
|
1017
|
-
}
|
1018
|
-
return rb_pgresult;
|
1019
|
-
}
|
1020
|
-
|
1021
|
-
/*
|
1022
|
-
* call-seq:
|
1023
|
-
* conn.prepare(stmt_name, sql [, param_types ] ) -> PGresult
|
1024
|
-
*
|
1025
|
-
* Prepares statement _sql_ with name _name_ to be executed later.
|
1026
|
-
* Returns a PGresult instance on success.
|
1027
|
-
* On failure, it raises a PGError exception.
|
1028
|
-
*
|
1029
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1030
|
-
* types of the parameters.
|
1031
|
-
*
|
1032
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1033
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1034
|
-
* explicit casts in the query to ensure that the right type is used.
|
1035
|
-
*
|
1036
|
-
* For example: "SELECT $1::int"
|
1037
|
-
*
|
1038
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1039
|
-
* inside the SQL query.
|
1040
|
-
*/
|
1041
|
-
static VALUE
|
1042
|
-
pgconn_prepare(int argc, VALUE *argv, VALUE self)
|
1043
|
-
{
|
1044
|
-
PGconn *conn = get_pgconn(self);
|
1045
|
-
PGresult *result = NULL;
|
1046
|
-
VALUE rb_pgresult;
|
1047
|
-
VALUE name, command, in_paramtypes;
|
1048
|
-
VALUE param;
|
1049
|
-
int i = 0;
|
1050
|
-
int nParams = 0;
|
1051
|
-
Oid *paramTypes = NULL;
|
1052
|
-
|
1053
|
-
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1054
|
-
Check_Type(name, T_STRING);
|
1055
|
-
Check_Type(command, T_STRING);
|
1056
|
-
|
1057
|
-
if(! NIL_P(in_paramtypes)) {
|
1058
|
-
Check_Type(in_paramtypes, T_ARRAY);
|
1059
|
-
nParams = RARRAY_LEN(in_paramtypes);
|
1060
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1061
|
-
for(i = 0; i < nParams; i++) {
|
1062
|
-
param = rb_ary_entry(in_paramtypes, i);
|
1063
|
-
Check_Type(param, T_FIXNUM);
|
1064
|
-
if(param == Qnil)
|
1065
|
-
paramTypes[i] = 0;
|
1066
|
-
else
|
1067
|
-
paramTypes[i] = NUM2INT(param);
|
1068
|
-
}
|
1069
|
-
}
|
1070
|
-
result = PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
|
1071
|
-
nParams, paramTypes);
|
1072
|
-
|
1073
|
-
xfree(paramTypes);
|
1074
|
-
|
1075
|
-
rb_pgresult = new_pgresult(result, conn);
|
1076
|
-
pgresult_check(self, rb_pgresult);
|
1077
|
-
return rb_pgresult;
|
1078
|
-
}
|
1079
|
-
|
1080
|
-
/*
|
1081
|
-
* call-seq:
|
1082
|
-
* conn.exec_prepared(statement_name [, params, result_format ] ) -> PGresult
|
1083
|
-
* conn.exec_prepared(statement_name [, params, result_format ] ) {|pg_result| block }
|
1084
|
-
*
|
1085
|
-
* Execute prepared named statement specified by _statement_name_.
|
1086
|
-
* Returns a PGresult instance on success.
|
1087
|
-
* On failure, it raises a PGError exception.
|
1088
|
-
*
|
1089
|
-
* +params+ is an array of the optional bind parameters for the
|
1090
|
-
* SQL query. Each element of the +params+ array may be either:
|
1091
|
-
* a hash of the form:
|
1092
|
-
* {:value => String (value of bind parameter)
|
1093
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1094
|
-
* }
|
1095
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1096
|
-
* { :value => <string value>, :format => 0 }
|
1097
|
-
*
|
1098
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1099
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1100
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1101
|
-
*
|
1102
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1103
|
-
* for binary.
|
1104
|
-
*
|
1105
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1106
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
1107
|
-
* In this instance, <code>conn.exec_prepared</code> returns the value of the block.
|
1108
|
-
*/
|
1109
|
-
static VALUE
|
1110
|
-
pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
|
1111
|
-
{
|
1112
|
-
PGconn *conn = get_pgconn(self);
|
1113
|
-
PGresult *result = NULL;
|
1114
|
-
VALUE rb_pgresult;
|
1115
|
-
VALUE name, params, in_res_fmt;
|
1116
|
-
VALUE param, param_value, param_format;
|
1117
|
-
VALUE param_value_tmp;
|
1118
|
-
VALUE sym_value, sym_format;
|
1119
|
-
VALUE gc_array;
|
1120
|
-
int i = 0;
|
1121
|
-
int nParams;
|
1122
|
-
char ** paramValues;
|
1123
|
-
int *paramLengths;
|
1124
|
-
int *paramFormats;
|
1125
|
-
int resultFormat;
|
1126
|
-
|
1127
|
-
|
1128
|
-
rb_scan_args(argc, argv, "12", &name, ¶ms, &in_res_fmt);
|
1129
|
-
Check_Type(name, T_STRING);
|
1130
|
-
|
1131
|
-
if(NIL_P(params)) {
|
1132
|
-
params = rb_ary_new2(0);
|
1133
|
-
resultFormat = 0;
|
1134
|
-
}
|
1135
|
-
else {
|
1136
|
-
Check_Type(params, T_ARRAY);
|
1137
|
-
}
|
1138
|
-
|
1139
|
-
if(NIL_P(in_res_fmt)) {
|
1140
|
-
resultFormat = 0;
|
1141
|
-
}
|
1142
|
-
else {
|
1143
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1144
|
-
}
|
1145
|
-
|
1146
|
-
gc_array = rb_ary_new();
|
1147
|
-
rb_gc_register_address(&gc_array);
|
1148
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1149
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1150
|
-
nParams = RARRAY_LEN(params);
|
1151
|
-
paramValues = ALLOC_N(char *, nParams);
|
1152
|
-
paramLengths = ALLOC_N(int, nParams);
|
1153
|
-
paramFormats = ALLOC_N(int, nParams);
|
1154
|
-
for(i = 0; i < nParams; i++) {
|
1155
|
-
param = rb_ary_entry(params, i);
|
1156
|
-
if (TYPE(param) == T_HASH) {
|
1157
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1158
|
-
if(param_value_tmp == Qnil)
|
1159
|
-
param_value = param_value_tmp;
|
1160
|
-
else
|
1161
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1162
|
-
param_format = rb_hash_aref(param, sym_format);
|
1163
|
-
}
|
1164
|
-
else {
|
1165
|
-
if(param == Qnil)
|
1166
|
-
param_value = param;
|
1167
|
-
else
|
1168
|
-
param_value = rb_obj_as_string(param);
|
1169
|
-
param_format = INT2NUM(0);
|
1170
|
-
}
|
1171
|
-
if(param_value == Qnil) {
|
1172
|
-
paramValues[i] = NULL;
|
1173
|
-
paramLengths[i] = 0;
|
1174
|
-
}
|
1175
|
-
else {
|
1176
|
-
Check_Type(param_value, T_STRING);
|
1177
|
-
/* make sure param_value doesn't get freed by the GC */
|
1178
|
-
rb_ary_push(gc_array, param_value);
|
1179
|
-
paramValues[i] = StringValuePtr(param_value);
|
1180
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1181
|
-
}
|
1182
|
-
|
1183
|
-
if(param_format == Qnil)
|
1184
|
-
paramFormats[i] = 0;
|
1185
|
-
else
|
1186
|
-
paramFormats[i] = NUM2INT(param_format);
|
1187
|
-
}
|
1188
|
-
|
1189
|
-
result = PQexecPrepared(conn, StringValuePtr(name), nParams,
|
1190
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1191
|
-
resultFormat);
|
1192
|
-
|
1193
|
-
rb_gc_unregister_address(&gc_array);
|
1194
|
-
|
1195
|
-
xfree(paramValues);
|
1196
|
-
xfree(paramLengths);
|
1197
|
-
xfree(paramFormats);
|
1198
|
-
|
1199
|
-
rb_pgresult = new_pgresult(result, conn);
|
1200
|
-
pgresult_check(self, rb_pgresult);
|
1201
|
-
if (rb_block_given_p()) {
|
1202
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1203
|
-
pgresult_clear, rb_pgresult);
|
1204
|
-
}
|
1205
|
-
return rb_pgresult;
|
1206
|
-
}
|
1207
|
-
|
1208
|
-
/*
|
1209
|
-
* call-seq:
|
1210
|
-
* conn.describe_prepared( statement_name ) -> PGresult
|
1211
|
-
*
|
1212
|
-
* Retrieve information about the prepared statement
|
1213
|
-
* _statement_name_.
|
1214
|
-
*/
|
1215
|
-
static VALUE
|
1216
|
-
pgconn_describe_prepared(VALUE self, VALUE stmt_name)
|
1217
|
-
{
|
1218
|
-
PGresult *result;
|
1219
|
-
VALUE rb_pgresult;
|
1220
|
-
PGconn *conn = get_pgconn(self);
|
1221
|
-
char *stmt;
|
1222
|
-
if(stmt_name == Qnil) {
|
1223
|
-
stmt = NULL;
|
1224
|
-
}
|
1225
|
-
else {
|
1226
|
-
Check_Type(stmt_name, T_STRING);
|
1227
|
-
stmt = StringValuePtr(stmt_name);
|
1228
|
-
}
|
1229
|
-
result = PQdescribePrepared(conn, stmt);
|
1230
|
-
rb_pgresult = new_pgresult(result, conn);
|
1231
|
-
pgresult_check(self, rb_pgresult);
|
1232
|
-
return rb_pgresult;
|
1233
|
-
}
|
1234
|
-
|
1235
|
-
|
1236
|
-
/*
|
1237
|
-
* call-seq:
|
1238
|
-
* conn.describe_portal( portal_name ) -> PGresult
|
1239
|
-
*
|
1240
|
-
* Retrieve information about the portal _portal_name_.
|
1241
|
-
*/
|
1242
|
-
static VALUE
|
1243
|
-
pgconn_describe_portal(self, stmt_name)
|
1244
|
-
VALUE self, stmt_name;
|
1245
|
-
{
|
1246
|
-
PGresult *result;
|
1247
|
-
VALUE rb_pgresult;
|
1248
|
-
PGconn *conn = get_pgconn(self);
|
1249
|
-
char *stmt;
|
1250
|
-
if(stmt_name == Qnil) {
|
1251
|
-
stmt = NULL;
|
1252
|
-
}
|
1253
|
-
else {
|
1254
|
-
Check_Type(stmt_name, T_STRING);
|
1255
|
-
stmt = StringValuePtr(stmt_name);
|
1256
|
-
}
|
1257
|
-
result = PQdescribePortal(conn, stmt);
|
1258
|
-
rb_pgresult = new_pgresult(result, conn);
|
1259
|
-
pgresult_check(self, rb_pgresult);
|
1260
|
-
return rb_pgresult;
|
1261
|
-
}
|
1262
|
-
|
1263
|
-
|
1264
|
-
/*
|
1265
|
-
* call-seq:
|
1266
|
-
* conn.make_empty_pgresult( status ) -> PGresult
|
1267
|
-
*
|
1268
|
-
* Constructs and empty PGresult with status _status_.
|
1269
|
-
* _status_ may be one of:
|
1270
|
-
* * +PGRES_EMPTY_QUERY+
|
1271
|
-
* * +PGRES_COMMAND_OK+
|
1272
|
-
* * +PGRES_TUPLES_OK+
|
1273
|
-
* * +PGRES_COPY_OUT+
|
1274
|
-
* * +PGRES_COPY_IN+
|
1275
|
-
* * +PGRES_BAD_RESPONSE+
|
1276
|
-
* * +PGRES_NONFATAL_ERROR+
|
1277
|
-
* * +PGRES_FATAL_ERROR+
|
1278
|
-
*/
|
1279
|
-
static VALUE
|
1280
|
-
pgconn_make_empty_pgresult(VALUE self, VALUE status)
|
1281
|
-
{
|
1282
|
-
PGresult *result;
|
1283
|
-
VALUE rb_pgresult;
|
1284
|
-
PGconn *conn = get_pgconn(self);
|
1285
|
-
result = PQmakeEmptyPGresult(conn, NUM2INT(status));
|
1286
|
-
rb_pgresult = new_pgresult(result, conn);
|
1287
|
-
pgresult_check(self, rb_pgresult);
|
1288
|
-
return rb_pgresult;
|
1289
|
-
}
|
1290
|
-
|
1291
|
-
|
1292
|
-
/*
|
1293
|
-
* call-seq:
|
1294
|
-
* conn.escape_string( str ) -> String
|
1295
|
-
*
|
1296
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1297
|
-
* uses PQescapeStringConn, which is safer. Avoid calling as a class method,
|
1298
|
-
* the class method uses the deprecated PQescapeString() API function.
|
1299
|
-
*
|
1300
|
-
* Returns a SQL-safe version of the String _str_.
|
1301
|
-
* This is the preferred way to make strings safe for inclusion in
|
1302
|
-
* SQL queries.
|
1303
|
-
*
|
1304
|
-
* Consider using exec_params, which avoids the need for passing values
|
1305
|
-
* inside of SQL commands.
|
1306
|
-
*
|
1307
|
-
* Encoding of escaped string will be equal to client encoding of connection.
|
1308
|
-
*/
|
1309
|
-
static VALUE
|
1310
|
-
pgconn_s_escape(VALUE self, VALUE string)
|
1311
|
-
{
|
1312
|
-
char *escaped;
|
1313
|
-
int size,error;
|
1314
|
-
VALUE result;
|
1315
|
-
#ifdef M17N_SUPPORTED
|
1316
|
-
rb_encoding* enc;
|
1317
|
-
#endif
|
1318
|
-
|
1319
|
-
Check_Type(string, T_STRING);
|
1320
|
-
|
1321
|
-
escaped = ALLOC_N(char, RSTRING_LEN(string) * 2 + 1);
|
1322
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1323
|
-
size = PQescapeStringConn(get_pgconn(self), escaped,
|
1324
|
-
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1325
|
-
if(error) {
|
1326
|
-
xfree(escaped);
|
1327
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(get_pgconn(self)));
|
1328
|
-
}
|
1329
|
-
} else {
|
1330
|
-
size = PQescapeString(escaped, RSTRING_PTR(string),
|
1331
|
-
RSTRING_LEN(string));
|
1332
|
-
}
|
1333
|
-
result = rb_str_new(escaped, size);
|
1334
|
-
xfree(escaped);
|
1335
|
-
OBJ_INFECT(result, string);
|
1336
|
-
|
1337
|
-
#ifdef M17N_SUPPORTED
|
1338
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1339
|
-
enc = pgconn_get_client_encoding_as_rb_encoding(get_pgconn(self));
|
1340
|
-
} else {
|
1341
|
-
enc = rb_enc_get(string);
|
1342
|
-
}
|
1343
|
-
rb_enc_associate(result, enc);
|
1344
|
-
#endif
|
1345
|
-
|
1346
|
-
return result;
|
1347
|
-
}
|
1348
|
-
|
1349
|
-
/*
|
1350
|
-
* call-seq:
|
1351
|
-
* conn.escape_bytea( string ) -> String
|
1352
|
-
*
|
1353
|
-
* Connection instance method for versions of 8.1 and higher of libpq
|
1354
|
-
* uses PQescapeByteaConn, which is safer. Avoid calling as a class method,
|
1355
|
-
* the class method uses the deprecated PQescapeBytea() API function.
|
1356
|
-
*
|
1357
|
-
* Use the instance method version of this function, it is safer than the
|
1358
|
-
* class method.
|
1359
|
-
*
|
1360
|
-
* Escapes binary data for use within an SQL command with the type +bytea+.
|
1361
|
-
*
|
1362
|
-
* Certain byte values must be escaped (but all byte values may be escaped)
|
1363
|
-
* when used as part of a +bytea+ literal in an SQL statement. In general, to
|
1364
|
-
* escape a byte, it is converted into the three digit octal number equal to
|
1365
|
-
* the octet value, and preceded by two backslashes. The single quote (') and
|
1366
|
-
* backslash (\) characters have special alternative escape sequences.
|
1367
|
-
* #escape_bytea performs this operation, escaping only the minimally required
|
1368
|
-
* bytes.
|
1369
|
-
*
|
1370
|
-
* Consider using exec_params, which avoids the need for passing values inside of
|
1371
|
-
* SQL commands.
|
1372
|
-
*/
|
1373
|
-
static VALUE
|
1374
|
-
pgconn_s_escape_bytea(VALUE self, VALUE str)
|
1375
|
-
{
|
1376
|
-
unsigned char *from, *to;
|
1377
|
-
size_t from_len, to_len;
|
1378
|
-
VALUE ret;
|
1379
|
-
|
1380
|
-
Check_Type(str, T_STRING);
|
1381
|
-
from = (unsigned char*)RSTRING_PTR(str);
|
1382
|
-
from_len = RSTRING_LEN(str);
|
1383
|
-
|
1384
|
-
if(rb_obj_class(self) == rb_cPGconn) {
|
1385
|
-
to = PQescapeByteaConn(get_pgconn(self), from, from_len, &to_len);
|
1386
|
-
} else {
|
1387
|
-
to = PQescapeBytea( from, from_len, &to_len);
|
1388
|
-
}
|
1389
|
-
|
1390
|
-
ret = rb_str_new((char*)to, to_len - 1);
|
1391
|
-
OBJ_INFECT(ret, str);
|
1392
|
-
PQfreemem(to);
|
1393
|
-
return ret;
|
1394
|
-
}
|
1395
|
-
|
1396
|
-
|
1397
|
-
/*
|
1398
|
-
* call-seq:
|
1399
|
-
* PGconn.unescape_bytea( string )
|
1400
|
-
*
|
1401
|
-
* Converts an escaped string representation of binary data into binary data --- the
|
1402
|
-
* reverse of #escape_bytea. This is needed when retrieving +bytea+ data in text format,
|
1403
|
-
* but not when retrieving it in binary format.
|
1404
|
-
*
|
1405
|
-
*/
|
1406
|
-
static VALUE
|
1407
|
-
pgconn_s_unescape_bytea(VALUE self, VALUE str)
|
1408
|
-
{
|
1409
|
-
unsigned char *from, *to;
|
1410
|
-
size_t to_len;
|
1411
|
-
VALUE ret;
|
1412
|
-
|
1413
|
-
Check_Type(str, T_STRING);
|
1414
|
-
from = (unsigned char*)StringValuePtr(str);
|
1415
|
-
|
1416
|
-
to = PQunescapeBytea(from, &to_len);
|
1417
|
-
|
1418
|
-
ret = rb_str_new((char*)to, to_len);
|
1419
|
-
OBJ_INFECT(ret, str);
|
1420
|
-
PQfreemem(to);
|
1421
|
-
return ret;
|
1422
|
-
}
|
1423
|
-
|
1424
|
-
/*
|
1425
|
-
* call-seq:
|
1426
|
-
* conn.send_query(sql [, params, result_format ] ) -> nil
|
1427
|
-
*
|
1428
|
-
* Sends SQL query request specified by _sql_ to PostgreSQL for
|
1429
|
-
* asynchronous processing, and immediately returns.
|
1430
|
-
* On failure, it raises a PGError exception.
|
1431
|
-
*
|
1432
|
-
* +params+ is an optional array of the bind parameters for the SQL query.
|
1433
|
-
* Each element of the +params+ array may be either:
|
1434
|
-
* a hash of the form:
|
1435
|
-
* {:value => String (value of bind parameter)
|
1436
|
-
* :type => Fixnum (oid of type of bind parameter)
|
1437
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1438
|
-
* }
|
1439
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1440
|
-
* { :value => <string value>, :type => 0, :format => 0 }
|
1441
|
-
*
|
1442
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1443
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1444
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1445
|
-
*
|
1446
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1447
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1448
|
-
* explicit casts in the query to ensure that the right type is used.
|
1449
|
-
*
|
1450
|
-
* For example: "SELECT $1::int"
|
1451
|
-
*
|
1452
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1453
|
-
* for binary.
|
1454
|
-
*/
|
1455
|
-
static VALUE
|
1456
|
-
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1457
|
-
{
|
1458
|
-
PGconn *conn = get_pgconn(self);
|
1459
|
-
int result;
|
1460
|
-
VALUE command, params, in_res_fmt;
|
1461
|
-
VALUE param, param_type, param_value, param_format;
|
1462
|
-
VALUE param_value_tmp;
|
1463
|
-
VALUE sym_type, sym_value, sym_format;
|
1464
|
-
VALUE gc_array;
|
1465
|
-
VALUE error;
|
1466
|
-
int i=0;
|
1467
|
-
int nParams;
|
1468
|
-
Oid *paramTypes;
|
1469
|
-
char ** paramValues;
|
1470
|
-
int *paramLengths;
|
1471
|
-
int *paramFormats;
|
1472
|
-
int resultFormat;
|
1473
|
-
|
1474
|
-
rb_scan_args(argc, argv, "12", &command, ¶ms, &in_res_fmt);
|
1475
|
-
Check_Type(command, T_STRING);
|
1476
|
-
|
1477
|
-
/* If called with no parameters, use PQsendQuery */
|
1478
|
-
if(NIL_P(params)) {
|
1479
|
-
if(PQsendQuery(conn,StringValuePtr(command)) == 0) {
|
1480
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1481
|
-
rb_iv_set(error, "@connection", self);
|
1482
|
-
rb_exc_raise(error);
|
1483
|
-
}
|
1484
|
-
return Qnil;
|
1485
|
-
}
|
1486
|
-
|
1487
|
-
/* If called with parameters, and optionally result_format,
|
1488
|
-
* use PQsendQueryParams
|
1489
|
-
*/
|
1490
|
-
Check_Type(params, T_ARRAY);
|
1491
|
-
|
1492
|
-
if(NIL_P(in_res_fmt)) {
|
1493
|
-
resultFormat = 0;
|
1494
|
-
}
|
1495
|
-
else {
|
1496
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1497
|
-
}
|
1498
|
-
|
1499
|
-
gc_array = rb_ary_new();
|
1500
|
-
rb_gc_register_address(&gc_array);
|
1501
|
-
sym_type = ID2SYM(rb_intern("type"));
|
1502
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1503
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1504
|
-
nParams = RARRAY_LEN(params);
|
1505
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1506
|
-
paramValues = ALLOC_N(char *, nParams);
|
1507
|
-
paramLengths = ALLOC_N(int, nParams);
|
1508
|
-
paramFormats = ALLOC_N(int, nParams);
|
1509
|
-
for(i = 0; i < nParams; i++) {
|
1510
|
-
param = rb_ary_entry(params, i);
|
1511
|
-
if (TYPE(param) == T_HASH) {
|
1512
|
-
param_type = rb_hash_aref(param, sym_type);
|
1513
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1514
|
-
if(param_value_tmp == Qnil)
|
1515
|
-
param_value = param_value_tmp;
|
1516
|
-
else
|
1517
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1518
|
-
param_format = rb_hash_aref(param, sym_format);
|
1519
|
-
}
|
1520
|
-
else {
|
1521
|
-
param_type = INT2NUM(0);
|
1522
|
-
if(param == Qnil)
|
1523
|
-
param_value = param;
|
1524
|
-
else
|
1525
|
-
param_value = rb_obj_as_string(param);
|
1526
|
-
param_format = INT2NUM(0);
|
1527
|
-
}
|
1528
|
-
|
1529
|
-
if(param_type == Qnil)
|
1530
|
-
paramTypes[i] = 0;
|
1531
|
-
else
|
1532
|
-
paramTypes[i] = NUM2INT(param_type);
|
1533
|
-
|
1534
|
-
if(param_value == Qnil) {
|
1535
|
-
paramValues[i] = NULL;
|
1536
|
-
paramLengths[i] = 0;
|
1537
|
-
}
|
1538
|
-
else {
|
1539
|
-
Check_Type(param_value, T_STRING);
|
1540
|
-
/* make sure param_value doesn't get freed by the GC */
|
1541
|
-
rb_ary_push(gc_array, param_value);
|
1542
|
-
paramValues[i] = StringValuePtr(param_value);
|
1543
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1544
|
-
}
|
1545
|
-
|
1546
|
-
if(param_format == Qnil)
|
1547
|
-
paramFormats[i] = 0;
|
1548
|
-
else
|
1549
|
-
paramFormats[i] = NUM2INT(param_format);
|
1550
|
-
}
|
1551
|
-
|
1552
|
-
result = PQsendQueryParams(conn, StringValuePtr(command), nParams, paramTypes,
|
1553
|
-
(const char * const *)paramValues, paramLengths, paramFormats, resultFormat);
|
1554
|
-
|
1555
|
-
rb_gc_unregister_address(&gc_array);
|
1556
|
-
|
1557
|
-
xfree(paramTypes);
|
1558
|
-
xfree(paramValues);
|
1559
|
-
xfree(paramLengths);
|
1560
|
-
xfree(paramFormats);
|
1561
|
-
|
1562
|
-
if(result == 0) {
|
1563
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1564
|
-
rb_iv_set(error, "@connection", self);
|
1565
|
-
rb_exc_raise(error);
|
1566
|
-
}
|
1567
|
-
return Qnil;
|
1568
|
-
}
|
1569
|
-
|
1570
|
-
/*
|
1571
|
-
* call-seq:
|
1572
|
-
* conn.send_prepare( stmt_name, sql [, param_types ] ) -> nil
|
1573
|
-
*
|
1574
|
-
* Prepares statement _sql_ with name _name_ to be executed later.
|
1575
|
-
* Sends prepare command asynchronously, and returns immediately.
|
1576
|
-
* On failure, it raises a PGError exception.
|
1577
|
-
*
|
1578
|
-
* +param_types+ is an optional parameter to specify the Oids of the
|
1579
|
-
* types of the parameters.
|
1580
|
-
*
|
1581
|
-
* If the types are not specified, they will be inferred by PostgreSQL.
|
1582
|
-
* Instead of specifying type oids, it's recommended to simply add
|
1583
|
-
* explicit casts in the query to ensure that the right type is used.
|
1584
|
-
*
|
1585
|
-
* For example: "SELECT $1::int"
|
1586
|
-
*
|
1587
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1588
|
-
* inside the SQL query.
|
1589
|
-
*/
|
1590
|
-
static VALUE
|
1591
|
-
pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
1592
|
-
{
|
1593
|
-
PGconn *conn = get_pgconn(self);
|
1594
|
-
int result;
|
1595
|
-
VALUE name, command, in_paramtypes;
|
1596
|
-
VALUE param;
|
1597
|
-
VALUE error;
|
1598
|
-
int i = 0;
|
1599
|
-
int nParams = 0;
|
1600
|
-
Oid *paramTypes = NULL;
|
1601
|
-
|
1602
|
-
rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
|
1603
|
-
Check_Type(name, T_STRING);
|
1604
|
-
Check_Type(command, T_STRING);
|
1605
|
-
|
1606
|
-
if(! NIL_P(in_paramtypes)) {
|
1607
|
-
Check_Type(in_paramtypes, T_ARRAY);
|
1608
|
-
nParams = RARRAY_LEN(in_paramtypes);
|
1609
|
-
paramTypes = ALLOC_N(Oid, nParams);
|
1610
|
-
for(i = 0; i < nParams; i++) {
|
1611
|
-
param = rb_ary_entry(in_paramtypes, i);
|
1612
|
-
Check_Type(param, T_FIXNUM);
|
1613
|
-
if(param == Qnil)
|
1614
|
-
paramTypes[i] = 0;
|
1615
|
-
else
|
1616
|
-
paramTypes[i] = NUM2INT(param);
|
1617
|
-
}
|
1618
|
-
}
|
1619
|
-
result = PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
|
1620
|
-
nParams, paramTypes);
|
1621
|
-
|
1622
|
-
xfree(paramTypes);
|
1623
|
-
|
1624
|
-
if(result == 0) {
|
1625
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1626
|
-
rb_iv_set(error, "@connection", self);
|
1627
|
-
rb_exc_raise(error);
|
1628
|
-
}
|
1629
|
-
return Qnil;
|
1630
|
-
}
|
1631
|
-
|
1632
|
-
/*
|
1633
|
-
* call-seq:
|
1634
|
-
* conn.send_query_prepared( statement_name [, params, result_format ] )
|
1635
|
-
* -> nil
|
1636
|
-
*
|
1637
|
-
* Execute prepared named statement specified by _statement_name_
|
1638
|
-
* asynchronously, and returns immediately.
|
1639
|
-
* On failure, it raises a PGError exception.
|
1640
|
-
*
|
1641
|
-
* +params+ is an array of the optional bind parameters for the
|
1642
|
-
* SQL query. Each element of the +params+ array may be either:
|
1643
|
-
* a hash of the form:
|
1644
|
-
* {:value => String (value of bind parameter)
|
1645
|
-
* :format => Fixnum (0 for text, 1 for binary)
|
1646
|
-
* }
|
1647
|
-
* or, it may be a String. If it is a string, that is equivalent to the hash:
|
1648
|
-
* { :value => <string value>, :format => 0 }
|
1649
|
-
*
|
1650
|
-
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
|
1651
|
-
* inside the SQL query. The 0th element of the +params+ array is bound
|
1652
|
-
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
|
1653
|
-
*
|
1654
|
-
* The optional +result_format+ should be 0 for text results, 1
|
1655
|
-
* for binary.
|
1656
|
-
*/
|
1657
|
-
static VALUE
|
1658
|
-
pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
1659
|
-
{
|
1660
|
-
PGconn *conn = get_pgconn(self);
|
1661
|
-
int result;
|
1662
|
-
VALUE name, params, in_res_fmt;
|
1663
|
-
VALUE param, param_value, param_format;
|
1664
|
-
VALUE param_value_tmp;
|
1665
|
-
VALUE sym_value, sym_format;
|
1666
|
-
VALUE gc_array;
|
1667
|
-
VALUE error;
|
1668
|
-
int i = 0;
|
1669
|
-
int nParams;
|
1670
|
-
char ** paramValues;
|
1671
|
-
int *paramLengths;
|
1672
|
-
int *paramFormats;
|
1673
|
-
int resultFormat;
|
1674
|
-
|
1675
|
-
rb_scan_args(argc, argv, "12", &name, ¶ms, &in_res_fmt);
|
1676
|
-
Check_Type(name, T_STRING);
|
1677
|
-
|
1678
|
-
if(NIL_P(params)) {
|
1679
|
-
params = rb_ary_new2(0);
|
1680
|
-
resultFormat = 0;
|
1681
|
-
}
|
1682
|
-
else {
|
1683
|
-
Check_Type(params, T_ARRAY);
|
1684
|
-
}
|
1685
|
-
|
1686
|
-
if(NIL_P(in_res_fmt)) {
|
1687
|
-
resultFormat = 0;
|
1688
|
-
}
|
1689
|
-
else {
|
1690
|
-
resultFormat = NUM2INT(in_res_fmt);
|
1691
|
-
}
|
1692
|
-
|
1693
|
-
gc_array = rb_ary_new();
|
1694
|
-
rb_gc_register_address(&gc_array);
|
1695
|
-
sym_value = ID2SYM(rb_intern("value"));
|
1696
|
-
sym_format = ID2SYM(rb_intern("format"));
|
1697
|
-
nParams = RARRAY_LEN(params);
|
1698
|
-
paramValues = ALLOC_N(char *, nParams);
|
1699
|
-
paramLengths = ALLOC_N(int, nParams);
|
1700
|
-
paramFormats = ALLOC_N(int, nParams);
|
1701
|
-
for(i = 0; i < nParams; i++) {
|
1702
|
-
param = rb_ary_entry(params, i);
|
1703
|
-
if (TYPE(param) == T_HASH) {
|
1704
|
-
param_value_tmp = rb_hash_aref(param, sym_value);
|
1705
|
-
if(param_value_tmp == Qnil)
|
1706
|
-
param_value = param_value_tmp;
|
1707
|
-
else
|
1708
|
-
param_value = rb_obj_as_string(param_value_tmp);
|
1709
|
-
param_format = rb_hash_aref(param, sym_format);
|
1710
|
-
}
|
1711
|
-
else {
|
1712
|
-
if(param == Qnil)
|
1713
|
-
param_value = param;
|
1714
|
-
else
|
1715
|
-
param_value = rb_obj_as_string(param);
|
1716
|
-
param_format = INT2NUM(0);
|
1717
|
-
}
|
1718
|
-
|
1719
|
-
if(param_value == Qnil) {
|
1720
|
-
paramValues[i] = NULL;
|
1721
|
-
paramLengths[i] = 0;
|
1722
|
-
}
|
1723
|
-
else {
|
1724
|
-
Check_Type(param_value, T_STRING);
|
1725
|
-
/* make sure param_value doesn't get freed by the GC */
|
1726
|
-
rb_ary_push(gc_array, param_value);
|
1727
|
-
paramValues[i] = StringValuePtr(param_value);
|
1728
|
-
paramLengths[i] = RSTRING_LEN(param_value);
|
1729
|
-
}
|
1730
|
-
|
1731
|
-
if(param_format == Qnil)
|
1732
|
-
paramFormats[i] = 0;
|
1733
|
-
else
|
1734
|
-
paramFormats[i] = NUM2INT(param_format);
|
1735
|
-
}
|
1736
|
-
|
1737
|
-
result = PQsendQueryPrepared(conn, StringValuePtr(name), nParams,
|
1738
|
-
(const char * const *)paramValues, paramLengths, paramFormats,
|
1739
|
-
resultFormat);
|
1740
|
-
|
1741
|
-
rb_gc_unregister_address(&gc_array);
|
1742
|
-
|
1743
|
-
xfree(paramValues);
|
1744
|
-
xfree(paramLengths);
|
1745
|
-
xfree(paramFormats);
|
1746
|
-
|
1747
|
-
if(result == 0) {
|
1748
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1749
|
-
rb_iv_set(error, "@connection", self);
|
1750
|
-
rb_exc_raise(error);
|
1751
|
-
}
|
1752
|
-
return Qnil;
|
1753
|
-
}
|
1754
|
-
|
1755
|
-
/*
|
1756
|
-
* call-seq:
|
1757
|
-
* conn.send_describe_prepared( statement_name ) -> nil
|
1758
|
-
*
|
1759
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1760
|
-
* Use in combination with +conn.get_result+.
|
1761
|
-
*/
|
1762
|
-
static VALUE
|
1763
|
-
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
1764
|
-
{
|
1765
|
-
VALUE error;
|
1766
|
-
PGconn *conn = get_pgconn(self);
|
1767
|
-
/* returns 0 on failure */
|
1768
|
-
if(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
|
1769
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1770
|
-
rb_iv_set(error, "@connection", self);
|
1771
|
-
rb_exc_raise(error);
|
1772
|
-
}
|
1773
|
-
return Qnil;
|
1774
|
-
}
|
1775
|
-
|
1776
|
-
|
1777
|
-
/*
|
1778
|
-
* call-seq:
|
1779
|
-
* conn.send_describe_portal( portal_name ) -> nil
|
1780
|
-
*
|
1781
|
-
* Asynchronously send _command_ to the server. Does not block.
|
1782
|
-
* Use in combination with +conn.get_result+.
|
1783
|
-
*/
|
1784
|
-
static VALUE
|
1785
|
-
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
1786
|
-
{
|
1787
|
-
VALUE error;
|
1788
|
-
PGconn *conn = get_pgconn(self);
|
1789
|
-
/* returns 0 on failure */
|
1790
|
-
if(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
|
1791
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1792
|
-
rb_iv_set(error, "@connection", self);
|
1793
|
-
rb_exc_raise(error);
|
1794
|
-
}
|
1795
|
-
return Qnil;
|
1796
|
-
}
|
1797
|
-
|
1798
|
-
|
1799
|
-
/*
|
1800
|
-
* call-seq:
|
1801
|
-
* conn.get_result() -> PGresult
|
1802
|
-
* conn.get_result() {|pg_result| block }
|
1803
|
-
*
|
1804
|
-
* Blocks waiting for the next result from a call to
|
1805
|
-
* +PGconn#send_query+ (or another asynchronous command), and returns
|
1806
|
-
* it. Returns +nil+ if no more results are available.
|
1807
|
-
*
|
1808
|
-
* Note: call this function repeatedly until it returns +nil+, or else
|
1809
|
-
* you will not be able to issue further commands.
|
1810
|
-
*
|
1811
|
-
* If the optional code block is given, it will be passed <i>result</i> as an argument,
|
1812
|
-
* and the PGresult object will automatically be cleared when the block terminates.
|
1813
|
-
* In this instance, <code>conn.exec</code> returns the value of the block.
|
1814
|
-
*/
|
1815
|
-
static VALUE
|
1816
|
-
pgconn_get_result(VALUE self)
|
1817
|
-
{
|
1818
|
-
PGconn *conn = get_pgconn(self);
|
1819
|
-
PGresult *result;
|
1820
|
-
VALUE rb_pgresult;
|
1821
|
-
|
1822
|
-
result = PQgetResult(conn);
|
1823
|
-
if(result == NULL)
|
1824
|
-
return Qnil;
|
1825
|
-
rb_pgresult = new_pgresult(result, conn);
|
1826
|
-
if (rb_block_given_p()) {
|
1827
|
-
return rb_ensure(rb_yield, rb_pgresult,
|
1828
|
-
pgresult_clear, rb_pgresult);
|
1829
|
-
}
|
1830
|
-
return rb_pgresult;
|
1831
|
-
}
|
1832
|
-
|
1833
|
-
/*
|
1834
|
-
* call-seq:
|
1835
|
-
* conn.consume_input()
|
1836
|
-
*
|
1837
|
-
* If input is available from the server, consume it.
|
1838
|
-
* After calling +consume_input+, you can check +is_busy+
|
1839
|
-
* or *notifies* to see if the state has changed.
|
1840
|
-
*/
|
1841
|
-
static VALUE
|
1842
|
-
pgconn_consume_input(self)
|
1843
|
-
VALUE self;
|
1844
|
-
{
|
1845
|
-
VALUE error;
|
1846
|
-
PGconn *conn = get_pgconn(self);
|
1847
|
-
/* returns 0 on error */
|
1848
|
-
if(PQconsumeInput(conn) == 0) {
|
1849
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1850
|
-
rb_iv_set(error, "@connection", self);
|
1851
|
-
rb_exc_raise(error);
|
1852
|
-
}
|
1853
|
-
return Qnil;
|
1854
|
-
}
|
1855
|
-
|
1856
|
-
/*
|
1857
|
-
* call-seq:
|
1858
|
-
* conn.is_busy() -> Boolean
|
1859
|
-
*
|
1860
|
-
* Returns +true+ if a command is busy, that is, if
|
1861
|
-
* PQgetResult would block. Otherwise returns +false+.
|
1862
|
-
*/
|
1863
|
-
static VALUE
|
1864
|
-
pgconn_is_busy(self)
|
1865
|
-
VALUE self;
|
1866
|
-
{
|
1867
|
-
return PQisBusy(get_pgconn(self)) ? Qtrue : Qfalse;
|
1868
|
-
}
|
1869
|
-
|
1870
|
-
/*
|
1871
|
-
* call-seq:
|
1872
|
-
* conn.setnonblocking(Boolean) -> nil
|
1873
|
-
*
|
1874
|
-
* Sets the nonblocking status of the connection.
|
1875
|
-
* In the blocking state, calls to PGconn#send_query
|
1876
|
-
* will block until the message is sent to the server,
|
1877
|
-
* but will not wait for the query results.
|
1878
|
-
* In the nonblocking state, calls to PGconn#send_query
|
1879
|
-
* will return an error if the socket is not ready for
|
1880
|
-
* writing.
|
1881
|
-
* Note: This function does not affect PGconn#exec, because
|
1882
|
-
* that function doesn't return until the server has
|
1883
|
-
* processed the query and returned the results.
|
1884
|
-
* Returns +nil+.
|
1885
|
-
*/
|
1886
|
-
static VALUE
|
1887
|
-
pgconn_setnonblocking(self, state)
|
1888
|
-
VALUE self, state;
|
1889
|
-
{
|
1890
|
-
int arg;
|
1891
|
-
VALUE error;
|
1892
|
-
PGconn *conn = get_pgconn(self);
|
1893
|
-
if(state == Qtrue)
|
1894
|
-
arg = 1;
|
1895
|
-
else if (state == Qfalse)
|
1896
|
-
arg = 0;
|
1897
|
-
else
|
1898
|
-
rb_raise(rb_eArgError, "Boolean value expected");
|
1899
|
-
|
1900
|
-
if(PQsetnonblocking(conn, arg) == -1) {
|
1901
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1902
|
-
rb_iv_set(error, "@connection", self);
|
1903
|
-
rb_exc_raise(error);
|
1904
|
-
}
|
1905
|
-
return Qnil;
|
1906
|
-
}
|
1907
|
-
|
1908
|
-
|
1909
|
-
/*
|
1910
|
-
* call-seq:
|
1911
|
-
* conn.isnonblocking() -> Boolean
|
1912
|
-
*
|
1913
|
-
* Returns +true+ if a command is busy, that is, if
|
1914
|
-
* PQgetResult would block. Otherwise returns +false+.
|
1915
|
-
*/
|
1916
|
-
static VALUE
|
1917
|
-
pgconn_isnonblocking(self)
|
1918
|
-
VALUE self;
|
1919
|
-
{
|
1920
|
-
return PQisnonblocking(get_pgconn(self)) ? Qtrue : Qfalse;
|
1921
|
-
}
|
1922
|
-
|
1923
|
-
/*
|
1924
|
-
* call-seq:
|
1925
|
-
* conn.flush() -> Boolean
|
1926
|
-
*
|
1927
|
-
* Attempts to flush any queued output data to the server.
|
1928
|
-
* Returns +true+ if data is successfully flushed, +false+
|
1929
|
-
* if not (can only return +false+ if connection is
|
1930
|
-
* nonblocking.
|
1931
|
-
* Raises PGError exception if some other failure occurred.
|
1932
|
-
*/
|
1933
|
-
static VALUE
|
1934
|
-
pgconn_flush(self)
|
1935
|
-
VALUE self;
|
1936
|
-
{
|
1937
|
-
PGconn *conn = get_pgconn(self);
|
1938
|
-
int ret;
|
1939
|
-
VALUE error;
|
1940
|
-
ret = PQflush(conn);
|
1941
|
-
if(ret == -1) {
|
1942
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
1943
|
-
rb_iv_set(error, "@connection", self);
|
1944
|
-
rb_exc_raise(error);
|
1945
|
-
}
|
1946
|
-
return (ret) ? Qfalse : Qtrue;
|
1947
|
-
}
|
1948
|
-
|
1949
|
-
/*
|
1950
|
-
* call-seq:
|
1951
|
-
* conn.cancel() -> String
|
1952
|
-
*
|
1953
|
-
* Requests cancellation of the command currently being
|
1954
|
-
* processed. (Only implemented in PostgreSQL >= 8.0)
|
1955
|
-
*
|
1956
|
-
* Returns +nil+ on success, or a string containing the
|
1957
|
-
* error message if a failure occurs.
|
1958
|
-
*/
|
1959
|
-
static VALUE
|
1960
|
-
pgconn_cancel(VALUE self)
|
1961
|
-
{
|
1962
|
-
#ifdef HAVE_PQGETCANCEL
|
1963
|
-
char errbuf[256];
|
1964
|
-
PGcancel *cancel;
|
1965
|
-
VALUE retval;
|
1966
|
-
int ret;
|
1967
|
-
|
1968
|
-
cancel = PQgetCancel(get_pgconn(self));
|
1969
|
-
if(cancel == NULL)
|
1970
|
-
rb_raise(rb_ePGError,"Invalid connection!");
|
1971
|
-
|
1972
|
-
ret = PQcancel(cancel, errbuf, 256);
|
1973
|
-
if(ret == 1)
|
1974
|
-
retval = Qnil;
|
1975
|
-
else
|
1976
|
-
retval = rb_str_new2(errbuf);
|
1977
|
-
|
1978
|
-
PQfreeCancel(cancel);
|
1979
|
-
return retval;
|
1980
|
-
#else
|
1981
|
-
rb_notimplement();
|
1982
|
-
#endif
|
1983
|
-
}
|
1984
|
-
|
1985
|
-
|
1986
|
-
/*
|
1987
|
-
* call-seq:
|
1988
|
-
* conn.notifies()
|
1989
|
-
*
|
1990
|
-
* Returns a hash of the unprocessed notifications.
|
1991
|
-
* If there is no unprocessed notifier, it returns +nil+.
|
1992
|
-
*/
|
1993
|
-
static VALUE
|
1994
|
-
pgconn_notifies(VALUE self)
|
1995
|
-
{
|
1996
|
-
PGconn* conn = get_pgconn(self);
|
1997
|
-
PGnotify *notification;
|
1998
|
-
VALUE hash;
|
1999
|
-
VALUE sym_relname, sym_be_pid, sym_extra;
|
2000
|
-
VALUE relname, be_pid, extra;
|
2001
|
-
|
2002
|
-
sym_relname = ID2SYM(rb_intern("relname"));
|
2003
|
-
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2004
|
-
sym_extra = ID2SYM(rb_intern("extra"));
|
2005
|
-
|
2006
|
-
notification = PQnotifies(conn);
|
2007
|
-
if (notification == NULL) {
|
2008
|
-
return Qnil;
|
2009
|
-
}
|
2010
|
-
|
2011
|
-
hash = rb_hash_new();
|
2012
|
-
relname = rb_tainted_str_new2(notification->relname);
|
2013
|
-
be_pid = INT2NUM(notification->be_pid);
|
2014
|
-
extra = rb_tainted_str_new2(PGNOTIFY_EXTRA(notification));
|
2015
|
-
|
2016
|
-
rb_hash_aset(hash, sym_relname, relname);
|
2017
|
-
rb_hash_aset(hash, sym_be_pid, be_pid);
|
2018
|
-
rb_hash_aset(hash, sym_extra, extra);
|
2019
|
-
|
2020
|
-
PQfreemem(notification);
|
2021
|
-
return hash;
|
2022
|
-
}
|
2023
|
-
|
2024
|
-
|
2025
|
-
#ifdef _WIN32
|
2026
|
-
/*
|
2027
|
-
* Duplicate the sockets from libpq and create temporary CRT FDs
|
2028
|
-
*/
|
2029
|
-
void create_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2030
|
-
{
|
2031
|
-
int i;
|
2032
|
-
crt_set->fd_count = os_set->fd_count;
|
2033
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2034
|
-
WSAPROTOCOL_INFO wsa_pi;
|
2035
|
-
/* dupicate the SOCKET */
|
2036
|
-
int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
|
2037
|
-
SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
|
2038
|
-
/* create the CRT fd so ruby can get back to the SOCKET */
|
2039
|
-
int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
|
2040
|
-
os_set->fd_array[i] = s;
|
2041
|
-
crt_set->fd_array[i] = fd;
|
2042
|
-
}
|
2043
|
-
}
|
2044
|
-
|
2045
|
-
/*
|
2046
|
-
* Clean up the CRT FDs from create_crt_fd()
|
2047
|
-
*/
|
2048
|
-
void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
|
2049
|
-
{
|
2050
|
-
int i;
|
2051
|
-
for (i = 0; i < os_set->fd_count; i++) {
|
2052
|
-
/* cleanup the CRT fd */
|
2053
|
-
_close(crt_set->fd_array[i]);
|
2054
|
-
/* cleanup the duplicated SOCKET */
|
2055
|
-
closesocket(os_set->fd_array[i]);
|
2056
|
-
}
|
2057
|
-
}
|
2058
|
-
#endif
|
2059
|
-
|
2060
|
-
/*
|
2061
|
-
* call-seq:
|
2062
|
-
* conn.wait_for_notify( [ timeout ] ) -> String
|
2063
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
|
2064
|
-
* conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
|
2065
|
-
*
|
2066
|
-
* Blocks while waiting for notification(s), or until the optional
|
2067
|
-
* _timeout_ is reached, whichever comes first. _timeout_ is
|
2068
|
-
* measured in seconds and can be fractional.
|
2069
|
-
*
|
2070
|
-
* Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
|
2071
|
-
* event otherwise. If used in block form, passes the name of the
|
2072
|
-
* NOTIFY +event+ and the generating +pid+ into the block.
|
2073
|
-
*
|
2074
|
-
* Under PostgreSQL 9.0 and later, if the notification is sent with
|
2075
|
-
* the optional +payload+ string, it will be given to the block as the
|
2076
|
-
* third argument.
|
2077
|
-
*
|
2078
|
-
*/
|
2079
|
-
static VALUE
|
2080
|
-
pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
|
2081
|
-
{
|
2082
|
-
PGconn *conn = get_pgconn( self );
|
2083
|
-
PGnotify *notification;
|
2084
|
-
int sd = PQsocket( conn );
|
2085
|
-
int ret;
|
2086
|
-
struct timeval timeout;
|
2087
|
-
struct timeval *ptimeout = NULL;
|
2088
|
-
VALUE timeout_in = Qnil, relname = Qnil, be_pid = Qnil, extra = Qnil;
|
2089
|
-
double timeout_sec;
|
2090
|
-
fd_set sd_rset;
|
2091
|
-
#ifdef _WIN32
|
2092
|
-
fd_set crt_sd_rset;
|
2093
|
-
#endif
|
2094
|
-
|
2095
|
-
if ( sd < 0 )
|
2096
|
-
rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
|
2097
|
-
|
2098
|
-
rb_scan_args( argc, argv, "01", &timeout_in );
|
2099
|
-
|
2100
|
-
if ( RTEST(timeout_in) ) {
|
2101
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2102
|
-
timeout.tv_sec = (long)timeout_sec;
|
2103
|
-
timeout.tv_usec = (long)( (timeout_sec - (long)timeout_sec) * 1e6 );
|
2104
|
-
ptimeout = &timeout;
|
2105
|
-
}
|
2106
|
-
|
2107
|
-
/* Check for notifications */
|
2108
|
-
while ( (notification = PQnotifies(conn)) == NULL ) {
|
2109
|
-
FD_ZERO( &sd_rset );
|
2110
|
-
FD_SET( sd, &sd_rset );
|
2111
|
-
|
2112
|
-
#ifdef _WIN32
|
2113
|
-
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2114
|
-
#endif
|
2115
|
-
|
2116
|
-
/* Wait for the socket to become readable before checking again */
|
2117
|
-
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2118
|
-
|
2119
|
-
#ifdef _WIN32
|
2120
|
-
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
2121
|
-
#endif
|
2122
|
-
|
2123
|
-
if ( ret < 0 )
|
2124
|
-
rb_sys_fail( 0 );
|
2125
|
-
|
2126
|
-
/* Return nil if the select timed out */
|
2127
|
-
if ( ret == 0 ) return Qnil;
|
2128
|
-
|
2129
|
-
/* Read the socket */
|
2130
|
-
if ( (ret = PQconsumeInput(conn)) != 1 )
|
2131
|
-
rb_raise( rb_ePGError, "PQconsumeInput == %d: %s", ret, PQerrorMessage(conn) );
|
2132
|
-
}
|
2133
|
-
|
2134
|
-
relname = rb_tainted_str_new2( notification->relname );
|
2135
|
-
ASSOCIATE_INDEX( relname, self );
|
2136
|
-
be_pid = INT2NUM( notification->be_pid );
|
2137
|
-
#ifdef HAVE_ST_NOTIFY_EXTRA
|
2138
|
-
if ( *notification->extra ) {
|
2139
|
-
extra = rb_tainted_str_new2( notification->extra );
|
2140
|
-
ASSOCIATE_INDEX( extra, self );
|
2141
|
-
}
|
2142
|
-
#endif
|
2143
|
-
PQfreemem( notification );
|
2144
|
-
|
2145
|
-
if ( rb_block_given_p() )
|
2146
|
-
rb_yield_values( 3, relname, be_pid, extra );
|
2147
|
-
|
2148
|
-
return relname;
|
2149
|
-
}
|
2150
|
-
|
2151
|
-
|
2152
|
-
/*
|
2153
|
-
* call-seq:
|
2154
|
-
* conn.put_copy_data( buffer ) -> Boolean
|
2155
|
-
*
|
2156
|
-
* Transmits _buffer_ as copy data to the server.
|
2157
|
-
* Returns true if the data was sent, false if it was
|
2158
|
-
* not sent (false is only possible if the connection
|
2159
|
-
* is in nonblocking mode, and this command would block).
|
2160
|
-
*
|
2161
|
-
* Raises an exception if an error occurs.
|
2162
|
-
*/
|
2163
|
-
static VALUE
|
2164
|
-
pgconn_put_copy_data(self, buffer)
|
2165
|
-
VALUE self, buffer;
|
2166
|
-
{
|
2167
|
-
int ret;
|
2168
|
-
VALUE error;
|
2169
|
-
PGconn *conn = get_pgconn(self);
|
2170
|
-
Check_Type(buffer, T_STRING);
|
2171
|
-
|
2172
|
-
ret = PQputCopyData(conn, RSTRING_PTR(buffer),
|
2173
|
-
RSTRING_LEN(buffer));
|
2174
|
-
if(ret == -1) {
|
2175
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2176
|
-
rb_iv_set(error, "@connection", self);
|
2177
|
-
rb_exc_raise(error);
|
2178
|
-
}
|
2179
|
-
return (ret) ? Qtrue : Qfalse;
|
2180
|
-
}
|
2181
|
-
|
2182
|
-
/*
|
2183
|
-
* call-seq:
|
2184
|
-
* conn.put_copy_end( [ error_message ] ) -> Boolean
|
2185
|
-
*
|
2186
|
-
* Sends end-of-data indication to the server.
|
2187
|
-
*
|
2188
|
-
* _error_message_ is an optional parameter, and if set,
|
2189
|
-
* forces the COPY command to fail with the string
|
2190
|
-
* _error_message_.
|
2191
|
-
*
|
2192
|
-
* Returns true if the end-of-data was sent, false if it was
|
2193
|
-
* not sent (false is only possible if the connection
|
2194
|
-
* is in nonblocking mode, and this command would block).
|
2195
|
-
*/
|
2196
|
-
static VALUE
|
2197
|
-
pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2198
|
-
{
|
2199
|
-
VALUE str;
|
2200
|
-
VALUE error;
|
2201
|
-
int ret;
|
2202
|
-
char *error_message = NULL;
|
2203
|
-
PGconn *conn = get_pgconn(self);
|
2204
|
-
|
2205
|
-
if (rb_scan_args(argc, argv, "01", &str) == 0)
|
2206
|
-
error_message = NULL;
|
2207
|
-
else
|
2208
|
-
error_message = StringValuePtr(str);
|
2209
|
-
|
2210
|
-
ret = PQputCopyEnd(conn, error_message);
|
2211
|
-
if(ret == -1) {
|
2212
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2213
|
-
rb_iv_set(error, "@connection", self);
|
2214
|
-
rb_exc_raise(error);
|
2215
|
-
}
|
2216
|
-
return (ret) ? Qtrue : Qfalse;
|
2217
|
-
}
|
2218
|
-
|
2219
|
-
/*
|
2220
|
-
* call-seq:
|
2221
|
-
* conn.get_copy_data( [ async = false ] ) -> String
|
2222
|
-
*
|
2223
|
-
* Return a string containing one row of data, +nil+
|
2224
|
-
* if the copy is done, or +false+ if the call would
|
2225
|
-
* block (only possible if _async_ is true).
|
2226
|
-
*
|
2227
|
-
*/
|
2228
|
-
static VALUE
|
2229
|
-
pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2230
|
-
{
|
2231
|
-
VALUE async_in;
|
2232
|
-
VALUE error;
|
2233
|
-
VALUE result_str;
|
2234
|
-
int ret;
|
2235
|
-
int async;
|
2236
|
-
char *buffer;
|
2237
|
-
PGconn *conn = get_pgconn(self);
|
2238
|
-
|
2239
|
-
if (rb_scan_args(argc, argv, "01", &async_in) == 0)
|
2240
|
-
async = 0;
|
2241
|
-
else
|
2242
|
-
async = (async_in == Qfalse || async_in == Qnil) ? 0 : 1;
|
2243
|
-
|
2244
|
-
ret = PQgetCopyData(conn, &buffer, async);
|
2245
|
-
if(ret == -2) { // error
|
2246
|
-
error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
|
2247
|
-
rb_iv_set(error, "@connection", self);
|
2248
|
-
rb_exc_raise(error);
|
2249
|
-
}
|
2250
|
-
if(ret == -1) { // No data left
|
2251
|
-
return Qnil;
|
2252
|
-
}
|
2253
|
-
if(ret == 0) { // would block
|
2254
|
-
return Qfalse;
|
2255
|
-
}
|
2256
|
-
result_str = rb_tainted_str_new(buffer, ret);
|
2257
|
-
PQfreemem(buffer);
|
2258
|
-
return result_str;
|
2259
|
-
}
|
2260
|
-
|
2261
|
-
/*
|
2262
|
-
* call-seq:
|
2263
|
-
* conn.set_error_verbosity( verbosity ) -> Fixnum
|
2264
|
-
*
|
2265
|
-
* Sets connection's verbosity to _verbosity_ and returns
|
2266
|
-
* the previous setting. Available settings are:
|
2267
|
-
* * PQERRORS_TERSE
|
2268
|
-
* * PQERRORS_DEFAULT
|
2269
|
-
* * PQERRORS_VERBOSE
|
2270
|
-
*/
|
2271
|
-
static VALUE
|
2272
|
-
pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
|
2273
|
-
{
|
2274
|
-
PGconn *conn = get_pgconn(self);
|
2275
|
-
PGVerbosity verbosity = NUM2INT(in_verbosity);
|
2276
|
-
return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
|
2277
|
-
}
|
2278
|
-
|
2279
|
-
/*
|
2280
|
-
* call-seq:
|
2281
|
-
* conn.trace( stream ) -> nil
|
2282
|
-
*
|
2283
|
-
* Enables tracing message passing between backend. The
|
2284
|
-
* trace message will be written to the stream _stream_,
|
2285
|
-
* which must implement a method +fileno+ that returns
|
2286
|
-
* a writable file descriptor.
|
2287
|
-
*/
|
2288
|
-
static VALUE
|
2289
|
-
pgconn_trace(VALUE self, VALUE stream)
|
2290
|
-
{
|
2291
|
-
VALUE fileno;
|
2292
|
-
FILE *new_fp;
|
2293
|
-
int old_fd, new_fd;
|
2294
|
-
VALUE new_file;
|
2295
|
-
|
2296
|
-
if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
|
2297
|
-
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2298
|
-
|
2299
|
-
fileno = rb_funcall(stream, rb_intern("fileno"), 0);
|
2300
|
-
if(fileno == Qnil)
|
2301
|
-
rb_raise(rb_eArgError, "can't get file descriptor from stream");
|
2302
|
-
|
2303
|
-
/* Duplicate the file descriptor and re-open
|
2304
|
-
* it. Then, make it into a ruby File object
|
2305
|
-
* and assign it to an instance variable.
|
2306
|
-
* This prevents a problem when the File
|
2307
|
-
* object passed to this function is closed
|
2308
|
-
* before the connection object is. */
|
2309
|
-
old_fd = NUM2INT(fileno);
|
2310
|
-
new_fd = dup(old_fd);
|
2311
|
-
new_fp = fdopen(new_fd, "w");
|
2312
|
-
|
2313
|
-
if(new_fp == NULL)
|
2314
|
-
rb_raise(rb_eArgError, "stream is not writable");
|
2315
|
-
|
2316
|
-
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2317
|
-
rb_iv_set(self, "@trace_stream", new_file);
|
2318
|
-
|
2319
|
-
PQtrace(get_pgconn(self), new_fp);
|
2320
|
-
return Qnil;
|
2321
|
-
}
|
2322
|
-
|
2323
|
-
/*
|
2324
|
-
* call-seq:
|
2325
|
-
* conn.untrace() -> nil
|
2326
|
-
*
|
2327
|
-
* Disables the message tracing.
|
2328
|
-
*/
|
2329
|
-
static VALUE
|
2330
|
-
pgconn_untrace(VALUE self)
|
2331
|
-
{
|
2332
|
-
VALUE trace_stream;
|
2333
|
-
PQuntrace(get_pgconn(self));
|
2334
|
-
trace_stream = rb_iv_get(self, "@trace_stream");
|
2335
|
-
rb_funcall(trace_stream, rb_intern("close"), 0);
|
2336
|
-
rb_iv_set(self, "@trace_stream", Qnil);
|
2337
|
-
return Qnil;
|
2338
|
-
}
|
2339
|
-
|
2340
|
-
/*
|
2341
|
-
* call-seq:
|
2342
|
-
* conn.set_notice_receiver {|result| ... } -> Proc
|
2343
|
-
*
|
2344
|
-
* Notice and warning messages generated by the server are not returned
|
2345
|
-
* by the query execution functions, since they do not imply failure of
|
2346
|
-
* the query. Instead they are passed to a notice handling function, and
|
2347
|
-
* execution continues normally after the handler returns. The default
|
2348
|
-
* notice handling function prints the message on <tt>stderr</tt>, but the
|
2349
|
-
* application can override this behavior by supplying its own handling
|
2350
|
-
* function.
|
2351
|
-
*
|
2352
|
-
* This function takes a new block to act as the handler, which should
|
2353
|
-
* accept a single parameter that will be a PGresult object, and returns
|
2354
|
-
* the Proc object previously set, or +nil+ if it was previously the default.
|
2355
|
-
*
|
2356
|
-
* If you pass no arguments, it will reset the handler to the default.
|
2357
|
-
*/
|
2358
|
-
static VALUE
|
2359
|
-
pgconn_set_notice_receiver(VALUE self)
|
2360
|
-
{
|
2361
|
-
VALUE proc, old_proc;
|
2362
|
-
PGconn *conn = get_pgconn(self);
|
2363
|
-
|
2364
|
-
/* If default_notice_receiver is unset, assume that the current
|
2365
|
-
* notice receiver is the default, and save it to a global variable.
|
2366
|
-
* This should not be a problem because the default receiver is
|
2367
|
-
* always the same, so won't vary among connections.
|
2368
|
-
*/
|
2369
|
-
if(default_notice_receiver == NULL)
|
2370
|
-
default_notice_receiver = PQsetNoticeReceiver(conn, NULL, NULL);
|
2371
|
-
|
2372
|
-
old_proc = rb_iv_get(self, "@notice_receiver");
|
2373
|
-
if( rb_block_given_p() ) {
|
2374
|
-
proc = rb_block_proc();
|
2375
|
-
PQsetNoticeReceiver(conn, notice_receiver_proxy, (void *)self);
|
2376
|
-
} else {
|
2377
|
-
/* if no block is given, set back to default */
|
2378
|
-
proc = Qnil;
|
2379
|
-
PQsetNoticeReceiver(conn, default_notice_receiver, NULL);
|
2380
|
-
}
|
2381
|
-
|
2382
|
-
rb_iv_set(self, "@notice_receiver", proc);
|
2383
|
-
return old_proc;
|
2384
|
-
}
|
2385
|
-
|
2386
|
-
/*
|
2387
|
-
* call-seq:
|
2388
|
-
* conn.set_notice_processor {|message| ... } -> Proc
|
2389
|
-
*
|
2390
|
-
* Notice and warning messages generated by the server are not returned
|
2391
|
-
* by the query execution functions, since they do not imply failure of
|
2392
|
-
* the query. Instead they are passed to a notice handling function, and
|
2393
|
-
* execution continues normally after the handler returns. The default
|
2394
|
-
* notice handling function prints the message on <tt>stderr</tt>, but the
|
2395
|
-
* application can override this behavior by supplying its own handling
|
2396
|
-
* function.
|
2397
|
-
*
|
2398
|
-
* This function takes a new block to act as the handler, which should
|
2399
|
-
* accept a single parameter that will be a PGresult object, and returns
|
2400
|
-
* the Proc object previously set, or +nil+ if it was previously the default.
|
2401
|
-
*
|
2402
|
-
* If you pass no arguments, it will reset the handler to the default.
|
2403
|
-
*/
|
2404
|
-
static VALUE
|
2405
|
-
pgconn_set_notice_processor(VALUE self)
|
2406
|
-
{
|
2407
|
-
VALUE proc, old_proc;
|
2408
|
-
PGconn *conn = get_pgconn(self);
|
2409
|
-
|
2410
|
-
/* If default_notice_processor is unset, assume that the current
|
2411
|
-
* notice processor is the default, and save it to a global variable.
|
2412
|
-
* This should not be a problem because the default processor is
|
2413
|
-
* always the same, so won't vary among connections.
|
2414
|
-
*/
|
2415
|
-
if(default_notice_processor == NULL)
|
2416
|
-
default_notice_processor = PQsetNoticeProcessor(conn, NULL, NULL);
|
2417
|
-
|
2418
|
-
old_proc = rb_iv_get(self, "@notice_processor");
|
2419
|
-
if( rb_block_given_p() ) {
|
2420
|
-
proc = rb_block_proc();
|
2421
|
-
PQsetNoticeProcessor(conn, notice_processor_proxy, (void *)self);
|
2422
|
-
} else {
|
2423
|
-
/* if no block is given, set back to default */
|
2424
|
-
proc = Qnil;
|
2425
|
-
PQsetNoticeProcessor(conn, default_notice_processor, NULL);
|
2426
|
-
}
|
2427
|
-
|
2428
|
-
rb_iv_set(self, "@notice_processor", proc);
|
2429
|
-
return old_proc;
|
2430
|
-
}
|
2431
|
-
/*
|
2432
|
-
* call-seq:
|
2433
|
-
* conn.get_client_encoding() -> String
|
2434
|
-
*
|
2435
|
-
* Returns the client encoding as a String.
|
2436
|
-
*/
|
2437
|
-
static VALUE
|
2438
|
-
pgconn_get_client_encoding(VALUE self)
|
2439
|
-
{
|
2440
|
-
char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(get_pgconn(self)));
|
2441
|
-
return rb_tainted_str_new2(encoding);
|
2442
|
-
}
|
2443
|
-
|
2444
|
-
/*
|
2445
|
-
* call-seq:
|
2446
|
-
* conn.set_client_encoding( encoding )
|
2447
|
-
*
|
2448
|
-
* Sets the client encoding to the _encoding_ String.
|
2449
|
-
*/
|
2450
|
-
static VALUE
|
2451
|
-
pgconn_set_client_encoding(VALUE self, VALUE str)
|
2452
|
-
{
|
2453
|
-
Check_Type(str, T_STRING);
|
2454
|
-
if ((PQsetClientEncoding(get_pgconn(self), StringValuePtr(str))) == -1){
|
2455
|
-
rb_raise(rb_ePGError, "invalid encoding name: %s",StringValuePtr(str));
|
2456
|
-
}
|
2457
|
-
return Qnil;
|
2458
|
-
}
|
2459
|
-
|
2460
|
-
/*
|
2461
|
-
* call-seq:
|
2462
|
-
* conn.transaction { |conn| ... } -> nil
|
2463
|
-
*
|
2464
|
-
* Executes a +BEGIN+ at the start of the block,
|
2465
|
-
* and a +COMMIT+ at the end of the block, or
|
2466
|
-
* +ROLLBACK+ if any exception occurs.
|
2467
|
-
*/
|
2468
|
-
static VALUE
|
2469
|
-
pgconn_transaction(VALUE self)
|
2470
|
-
{
|
2471
|
-
PGconn *conn = get_pgconn(self);
|
2472
|
-
PGresult *result;
|
2473
|
-
VALUE rb_pgresult;
|
2474
|
-
int status;
|
2475
|
-
|
2476
|
-
if (rb_block_given_p()) {
|
2477
|
-
result = PQexec(conn, "BEGIN");
|
2478
|
-
rb_pgresult = new_pgresult(result, conn);
|
2479
|
-
pgresult_check(self, rb_pgresult);
|
2480
|
-
rb_protect(rb_yield, self, &status);
|
2481
|
-
if(status == 0) {
|
2482
|
-
result = PQexec(conn, "COMMIT");
|
2483
|
-
rb_pgresult = new_pgresult(result, conn);
|
2484
|
-
pgresult_check(self, rb_pgresult);
|
2485
|
-
}
|
2486
|
-
else {
|
2487
|
-
/* exception occurred, ROLLBACK and re-raise */
|
2488
|
-
result = PQexec(conn, "ROLLBACK");
|
2489
|
-
rb_pgresult = new_pgresult(result, conn);
|
2490
|
-
pgresult_check(self, rb_pgresult);
|
2491
|
-
rb_jump_tag(status);
|
2492
|
-
}
|
2493
|
-
|
2494
|
-
}
|
2495
|
-
else {
|
2496
|
-
/* no block supplied? */
|
2497
|
-
rb_raise(rb_eArgError, "Must supply block for PGconn#transaction");
|
2498
|
-
}
|
2499
|
-
return Qnil;
|
2500
|
-
}
|
2501
|
-
|
2502
|
-
|
2503
|
-
/*
|
2504
|
-
* call-seq:
|
2505
|
-
* PGconn.quote_ident( str ) -> String
|
2506
|
-
* conn.quote_ident( str ) -> String
|
2507
|
-
*
|
2508
|
-
* Returns a string that is safe for inclusion in a SQL query as an
|
2509
|
-
* identifier. Note: this is not a quote function for values, but for
|
2510
|
-
* identifiers.
|
2511
|
-
*
|
2512
|
-
* For example, in a typical SQL query: <tt>SELECT FOO FROM MYTABLE</tt>
|
2513
|
-
* The identifier <tt>FOO</tt> is folded to lower case, so it actually
|
2514
|
-
* means <tt>foo</tt>. If you really want to access the case-sensitive
|
2515
|
-
* field name <tt>FOO</tt>, use this function like
|
2516
|
-
* <tt>PGconn.quote_ident('FOO')</tt>, which will return <tt>"FOO"</tt>
|
2517
|
-
* (with double-quotes). PostgreSQL will see the double-quotes, and
|
2518
|
-
* it will not fold to lower case.
|
2519
|
-
*
|
2520
|
-
* Similarly, this function also protects against special characters,
|
2521
|
-
* and other things that might allow SQL injection if the identifier
|
2522
|
-
* comes from an untrusted source.
|
2523
|
-
*/
|
2524
|
-
static VALUE
|
2525
|
-
pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
2526
|
-
{
|
2527
|
-
VALUE ret;
|
2528
|
-
char *str = StringValuePtr(in_str);
|
2529
|
-
/* result size at most NAMEDATALEN*2 plus surrounding
|
2530
|
-
* double-quotes. */
|
2531
|
-
char buffer[NAMEDATALEN*2+2];
|
2532
|
-
unsigned int i=0,j=0;
|
2533
|
-
|
2534
|
-
if(strlen(str) >= NAMEDATALEN) {
|
2535
|
-
rb_raise(rb_eArgError,
|
2536
|
-
"Input string is longer than NAMEDATALEN-1 (%d)",
|
2537
|
-
NAMEDATALEN-1);
|
2538
|
-
}
|
2539
|
-
buffer[j++] = '"';
|
2540
|
-
for(i = 0; i < strlen(str) && str[i]; i++) {
|
2541
|
-
if(str[i] == '"')
|
2542
|
-
buffer[j++] = '"';
|
2543
|
-
buffer[j++] = str[i];
|
2544
|
-
}
|
2545
|
-
buffer[j++] = '"';
|
2546
|
-
ret = rb_str_new(buffer,j);
|
2547
|
-
OBJ_INFECT(ret, in_str);
|
2548
|
-
return ret;
|
2549
|
-
}
|
2550
|
-
|
2551
|
-
|
2552
|
-
#ifndef _WIN32
|
2553
|
-
|
2554
|
-
/*
|
2555
|
-
* call-seq:
|
2556
|
-
* conn.block( [ timeout ] ) -> Boolean
|
2557
|
-
*
|
2558
|
-
* Blocks until the server is no longer busy, or until the
|
2559
|
-
* optional _timeout_ is reached, whichever comes first.
|
2560
|
-
* _timeout_ is measured in seconds and can be fractional.
|
2561
|
-
*
|
2562
|
-
* Returns +false+ if _timeout_ is reached, +true+ otherwise.
|
2563
|
-
*
|
2564
|
-
* If +true+ is returned, +conn.is_busy+ will return +false+
|
2565
|
-
* and +conn.get_result+ will not block.
|
2566
|
-
*/
|
2567
|
-
static VALUE
|
2568
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2569
|
-
PGconn *conn = get_pgconn( self );
|
2570
|
-
int sd = PQsocket( conn );
|
2571
|
-
int ret;
|
2572
|
-
|
2573
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2574
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2575
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2576
|
-
|
2577
|
-
struct timeval timeout;
|
2578
|
-
struct timeval *ptimeout = NULL;
|
2579
|
-
fd_set sd_rset;
|
2580
|
-
VALUE timeout_in;
|
2581
|
-
double timeout_sec;
|
2582
|
-
|
2583
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2584
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2585
|
-
timeout.tv_sec = (long)timeout_sec;
|
2586
|
-
timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
|
2587
|
-
ptimeout = &timeout;
|
2588
|
-
}
|
2589
|
-
|
2590
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2591
|
-
if ( PQconsumeInput(conn) == 0 )
|
2592
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2593
|
-
|
2594
|
-
while ( PQisBusy(conn) ) {
|
2595
|
-
FD_ZERO( &sd_rset );
|
2596
|
-
FD_SET( sd, &sd_rset );
|
2597
|
-
|
2598
|
-
if ( (ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout )) < 0 )
|
2599
|
-
rb_sys_fail( "rb_thread_select()" ); /* Raises */
|
2600
|
-
|
2601
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2602
|
-
if ( ret == 0 && argc )
|
2603
|
-
return Qfalse;
|
2604
|
-
|
2605
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2606
|
-
if ( PQconsumeInput(conn) == 0 )
|
2607
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2608
|
-
}
|
2609
|
-
|
2610
|
-
return Qtrue;
|
2611
|
-
}
|
2612
|
-
|
2613
|
-
|
2614
|
-
#else /* _WIN32 */
|
2615
|
-
|
2616
|
-
/*
|
2617
|
-
* Win32 PGconn#block -- on Windows, use platform-specific strategies to wait for the socket
|
2618
|
-
* instead of rb_thread_select().
|
2619
|
-
*/
|
2620
|
-
|
2621
|
-
/* Win32 + Ruby 1.9+ */
|
2622
|
-
#ifdef HAVE_RUBY_VM_H
|
2623
|
-
|
2624
|
-
int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
|
2625
|
-
|
2626
|
-
/* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
|
2627
|
-
* and does not wait (nor sleep) any time even if timeout is given.
|
2628
|
-
* Instead use the Winsock events and rb_w32_wait_events(). */
|
2629
|
-
|
2630
|
-
static VALUE
|
2631
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2632
|
-
PGconn *conn = get_pgconn( self );
|
2633
|
-
int sd = PQsocket( conn );
|
2634
|
-
int ret;
|
2635
|
-
|
2636
|
-
DWORD timeout_milisec = INFINITY;
|
2637
|
-
DWORD wait_ret;
|
2638
|
-
WSAEVENT hEvent;
|
2639
|
-
VALUE timeout_in;
|
2640
|
-
double timeout_sec;
|
2641
|
-
|
2642
|
-
hEvent = WSACreateEvent();
|
2643
|
-
|
2644
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2645
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2646
|
-
timeout_milisec = (DWORD)( (timeout_sec - (DWORD)timeout_sec) * 1e3 );
|
2647
|
-
}
|
2648
|
-
|
2649
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2650
|
-
if( PQconsumeInput(conn) == 0 ) {
|
2651
|
-
WSACloseEvent( hEvent );
|
2652
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2653
|
-
}
|
2654
|
-
|
2655
|
-
while ( PQisBusy(conn) ) {
|
2656
|
-
if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
|
2657
|
-
WSACloseEvent( hEvent );
|
2658
|
-
rb_raise( rb_ePGError, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2659
|
-
}
|
2660
|
-
|
2661
|
-
wait_ret = rb_w32_wait_events( &hEvent, 1, 100 );
|
2662
|
-
|
2663
|
-
if ( wait_ret == WAIT_TIMEOUT ) {
|
2664
|
-
ret = 0;
|
2665
|
-
} else if ( wait_ret == WAIT_OBJECT_0 ) {
|
2666
|
-
ret = 1;
|
2667
|
-
} else if ( wait_ret == WAIT_FAILED ) {
|
2668
|
-
WSACloseEvent( hEvent );
|
2669
|
-
rb_raise( rb_ePGError, "Wait on socket error (WaitForMultipleObjects): %d", GetLastError() );
|
2670
|
-
} else {
|
2671
|
-
WSACloseEvent( hEvent );
|
2672
|
-
rb_raise( rb_ePGError, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2673
|
-
}
|
2674
|
-
|
2675
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2676
|
-
if ( ret == 0 && argc ) {
|
2677
|
-
WSACloseEvent( hEvent );
|
2678
|
-
return Qfalse;
|
2679
|
-
}
|
2680
|
-
|
2681
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2682
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
2683
|
-
WSACloseEvent( hEvent );
|
2684
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2685
|
-
}
|
2686
|
-
}
|
2687
|
-
|
2688
|
-
WSACloseEvent( hEvent );
|
2689
|
-
|
2690
|
-
return Qtrue;
|
2691
|
-
}
|
2692
|
-
|
2693
|
-
#else /* Win32 + Ruby < 1.9 */
|
2694
|
-
|
2695
|
-
static VALUE
|
2696
|
-
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2697
|
-
PGconn *conn = get_pgconn( self );
|
2698
|
-
int sd = PQsocket( conn );
|
2699
|
-
int ret;
|
2700
|
-
|
2701
|
-
struct timeval timeout;
|
2702
|
-
struct timeval *ptimeout = NULL;
|
2703
|
-
fd_set sd_rset;
|
2704
|
-
fd_set crt_sd_rset;
|
2705
|
-
VALUE timeout_in;
|
2706
|
-
double timeout_sec;
|
2707
|
-
|
2708
|
-
/* Always set a timeout, as rb_thread_select() sometimes
|
2709
|
-
* doesn't return when a second ruby thread is running although data
|
2710
|
-
* could be read. So we use timeout-based polling instead.
|
2711
|
-
*/
|
2712
|
-
timeout.tv_sec = 0;
|
2713
|
-
timeout.tv_usec = 10000; // 10ms
|
2714
|
-
ptimeout = &timeout;
|
2715
|
-
|
2716
|
-
if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
|
2717
|
-
timeout_sec = NUM2DBL( timeout_in );
|
2718
|
-
timeout.tv_sec = (long)timeout_sec;
|
2719
|
-
timeout.tv_usec = (long)((timeout_sec - (long)timeout_sec) * 1e6);
|
2720
|
-
ptimeout = &timeout;
|
2721
|
-
}
|
2722
|
-
|
2723
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2724
|
-
if( PQconsumeInput(conn) == 0 )
|
2725
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2726
|
-
|
2727
|
-
while ( PQisBusy(conn) ) {
|
2728
|
-
FD_ZERO( &sd_rset );
|
2729
|
-
FD_SET( sd, &sd_rset );
|
2730
|
-
|
2731
|
-
create_crt_fd( &sd_rset, &crt_sd_rset );
|
2732
|
-
ret = rb_thread_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
|
2733
|
-
cleanup_crt_fd( &sd_rset, &crt_sd_rset );
|
2734
|
-
|
2735
|
-
/* Return false if there was a timeout argument and the select() timed out */
|
2736
|
-
if ( ret == 0 && argc )
|
2737
|
-
return Qfalse;
|
2738
|
-
|
2739
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2740
|
-
if ( PQconsumeInput(conn) == 0 )
|
2741
|
-
rb_raise( rb_ePGError, PQerrorMessage(conn) );
|
2742
|
-
}
|
2743
|
-
|
2744
|
-
return Qtrue;
|
2745
|
-
}
|
2746
|
-
|
2747
|
-
#endif /* Ruby 1.9 */
|
2748
|
-
#endif /* Win32 */
|
2749
|
-
|
2750
|
-
|
2751
|
-
/*
|
2752
|
-
* call-seq:
|
2753
|
-
* conn.get_last_result( ) -> PGresult
|
2754
|
-
*
|
2755
|
-
* This function retrieves all available results
|
2756
|
-
* on the current connection (from previously issued
|
2757
|
-
* asynchronous commands like +send_query()+) and
|
2758
|
-
* returns the last non-NULL result, or +nil+ if no
|
2759
|
-
* results are available.
|
2760
|
-
*
|
2761
|
-
* This function is similar to +PGconn#get_result+
|
2762
|
-
* except that it is designed to get one and only
|
2763
|
-
* one result.
|
2764
|
-
*/
|
2765
|
-
static VALUE
|
2766
|
-
pgconn_get_last_result(VALUE self)
|
2767
|
-
{
|
2768
|
-
PGconn *conn = get_pgconn(self);
|
2769
|
-
VALUE rb_pgresult = Qnil;
|
2770
|
-
PGresult *cur, *prev;
|
2771
|
-
|
2772
|
-
|
2773
|
-
cur = prev = NULL;
|
2774
|
-
while ((cur = PQgetResult(conn)) != NULL) {
|
2775
|
-
int status;
|
2776
|
-
|
2777
|
-
if (prev) PQclear(prev);
|
2778
|
-
prev = cur;
|
2779
|
-
|
2780
|
-
status = PQresultStatus(cur);
|
2781
|
-
if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
|
2782
|
-
break;
|
2783
|
-
}
|
2784
|
-
|
2785
|
-
if (prev) {
|
2786
|
-
rb_pgresult = new_pgresult(prev, conn);
|
2787
|
-
pgresult_check(self, rb_pgresult);
|
2788
|
-
}
|
2789
|
-
|
2790
|
-
return rb_pgresult;
|
2791
|
-
}
|
2792
|
-
|
2793
|
-
|
2794
|
-
/*
|
2795
|
-
* call-seq:
|
2796
|
-
* conn.async_exec(sql [, params, result_format ] ) -> PGresult
|
2797
|
-
* conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
|
2798
|
-
*
|
2799
|
-
* This function has the same behavior as +PGconn#exec+,
|
2800
|
-
* except that it's implemented using asynchronous command
|
2801
|
-
* processing and ruby's +rb_thread_select+ in order to
|
2802
|
-
* allow other threads to process while waiting for the
|
2803
|
-
* server to complete the request.
|
2804
|
-
*/
|
2805
|
-
static VALUE
|
2806
|
-
pgconn_async_exec(int argc, VALUE *argv, VALUE self)
|
2807
|
-
{
|
2808
|
-
VALUE rb_pgresult = Qnil;
|
2809
|
-
|
2810
|
-
/* remove any remaining results from the queue */
|
2811
|
-
pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
|
2812
|
-
pgconn_get_last_result( self );
|
2813
|
-
|
2814
|
-
pgconn_send_query( argc, argv, self );
|
2815
|
-
pgconn_block( 0, NULL, self );
|
2816
|
-
rb_pgresult = pgconn_get_last_result( self );
|
2817
|
-
|
2818
|
-
if ( rb_block_given_p() ) {
|
2819
|
-
return rb_ensure( rb_yield, rb_pgresult, pgresult_clear, rb_pgresult );
|
2820
|
-
}
|
2821
|
-
return rb_pgresult;
|
2822
|
-
}
|
2823
|
-
|
2824
|
-
|
2825
|
-
/**************************************************************************
|
2826
|
-
* LARGE OBJECT SUPPORT
|
2827
|
-
**************************************************************************/
|
2828
|
-
|
2829
|
-
/*
|
2830
|
-
* call-seq:
|
2831
|
-
* conn.lo_creat( [mode] ) -> Fixnum
|
2832
|
-
*
|
2833
|
-
* Creates a large object with mode _mode_. Returns a large object Oid.
|
2834
|
-
* On failure, it raises PGError exception.
|
2835
|
-
*/
|
2836
|
-
static VALUE
|
2837
|
-
pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
2838
|
-
{
|
2839
|
-
Oid lo_oid;
|
2840
|
-
int mode;
|
2841
|
-
VALUE nmode;
|
2842
|
-
PGconn *conn = get_pgconn(self);
|
2843
|
-
|
2844
|
-
if (rb_scan_args(argc, argv, "01", &nmode) == 0)
|
2845
|
-
mode = INV_READ;
|
2846
|
-
else
|
2847
|
-
mode = NUM2INT(nmode);
|
2848
|
-
|
2849
|
-
lo_oid = lo_creat(conn, mode);
|
2850
|
-
if (lo_oid == 0)
|
2851
|
-
rb_raise(rb_ePGError, "lo_creat failed");
|
2852
|
-
|
2853
|
-
return INT2FIX(lo_oid);
|
2854
|
-
}
|
2855
|
-
|
2856
|
-
/*
|
2857
|
-
* call-seq:
|
2858
|
-
* conn.lo_create( oid ) -> Fixnum
|
2859
|
-
*
|
2860
|
-
* Creates a large object with oid _oid_. Returns the large object Oid.
|
2861
|
-
* On failure, it raises PGError exception.
|
2862
|
-
*/
|
2863
|
-
static VALUE
|
2864
|
-
pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
2865
|
-
{
|
2866
|
-
Oid ret, lo_oid;
|
2867
|
-
PGconn *conn = get_pgconn(self);
|
2868
|
-
lo_oid = NUM2INT(in_lo_oid);
|
2869
|
-
|
2870
|
-
ret = lo_create(conn, in_lo_oid);
|
2871
|
-
if (ret == InvalidOid)
|
2872
|
-
rb_raise(rb_ePGError, "lo_create failed");
|
2873
|
-
|
2874
|
-
return INT2FIX(ret);
|
2875
|
-
}
|
2876
|
-
|
2877
|
-
/*
|
2878
|
-
* call-seq:
|
2879
|
-
* conn.lo_import(file) -> Fixnum
|
2880
|
-
*
|
2881
|
-
* Import a file to a large object. Returns a large object Oid.
|
2882
|
-
*
|
2883
|
-
* On failure, it raises a PGError exception.
|
2884
|
-
*/
|
2885
|
-
static VALUE
|
2886
|
-
pgconn_loimport(VALUE self, VALUE filename)
|
2887
|
-
{
|
2888
|
-
Oid lo_oid;
|
2889
|
-
|
2890
|
-
PGconn *conn = get_pgconn(self);
|
2891
|
-
|
2892
|
-
Check_Type(filename, T_STRING);
|
2893
|
-
|
2894
|
-
lo_oid = lo_import(conn, StringValuePtr(filename));
|
2895
|
-
if (lo_oid == 0) {
|
2896
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(conn));
|
2897
|
-
}
|
2898
|
-
return INT2FIX(lo_oid);
|
2899
|
-
}
|
2900
|
-
|
2901
|
-
/*
|
2902
|
-
* call-seq:
|
2903
|
-
* conn.lo_export( oid, file ) -> nil
|
2904
|
-
*
|
2905
|
-
* Saves a large object of _oid_ to a _file_.
|
2906
|
-
*/
|
2907
|
-
static VALUE
|
2908
|
-
pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
2909
|
-
{
|
2910
|
-
PGconn *conn = get_pgconn(self);
|
2911
|
-
int oid;
|
2912
|
-
Check_Type(filename, T_STRING);
|
2913
|
-
|
2914
|
-
oid = NUM2INT(lo_oid);
|
2915
|
-
if (oid < 0) {
|
2916
|
-
rb_raise(rb_ePGError, "invalid large object oid %d",oid);
|
2917
|
-
}
|
2918
|
-
|
2919
|
-
if (lo_export(conn, oid, StringValuePtr(filename)) < 0) {
|
2920
|
-
rb_raise(rb_ePGError, "%s", PQerrorMessage(conn));
|
2921
|
-
}
|
2922
|
-
return Qnil;
|
2923
|
-
}
|
2924
|
-
|
2925
|
-
/*
|
2926
|
-
* call-seq:
|
2927
|
-
* conn.lo_open( oid, [mode] ) -> Fixnum
|
2928
|
-
*
|
2929
|
-
* Open a large object of _oid_. Returns a large object descriptor
|
2930
|
-
* instance on success. The _mode_ argument specifies the mode for
|
2931
|
-
* the opened large object,which is either +INV_READ+, or +INV_WRITE+.
|
2932
|
-
*
|
2933
|
-
* If _mode_ is omitted, the default is +INV_READ+.
|
2934
|
-
*/
|
2935
|
-
static VALUE
|
2936
|
-
pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
2937
|
-
{
|
2938
|
-
Oid lo_oid;
|
2939
|
-
int fd, mode;
|
2940
|
-
VALUE nmode, selfid;
|
2941
|
-
PGconn *conn = get_pgconn(self);
|
2942
|
-
|
2943
|
-
rb_scan_args(argc, argv, "11", &selfid, &nmode);
|
2944
|
-
lo_oid = NUM2INT(selfid);
|
2945
|
-
if(NIL_P(nmode))
|
2946
|
-
mode = INV_READ;
|
2947
|
-
else
|
2948
|
-
mode = NUM2INT(nmode);
|
2949
|
-
|
2950
|
-
if((fd = lo_open(conn, lo_oid, mode)) < 0) {
|
2951
|
-
rb_raise(rb_ePGError, "can't open large object: %s", PQerrorMessage(conn));
|
2952
|
-
}
|
2953
|
-
return INT2FIX(fd);
|
2954
|
-
}
|
2955
|
-
|
2956
|
-
/*
|
2957
|
-
* call-seq:
|
2958
|
-
* conn.lo_write( lo_desc, buffer ) -> Fixnum
|
2959
|
-
*
|
2960
|
-
* Writes the string _buffer_ to the large object _lo_desc_.
|
2961
|
-
* Returns the number of bytes written.
|
2962
|
-
*/
|
2963
|
-
static VALUE
|
2964
|
-
pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
2965
|
-
{
|
2966
|
-
int n;
|
2967
|
-
PGconn *conn = get_pgconn(self);
|
2968
|
-
int fd = NUM2INT(in_lo_desc);
|
2969
|
-
|
2970
|
-
Check_Type(buffer, T_STRING);
|
2971
|
-
|
2972
|
-
if( RSTRING_LEN(buffer) < 0) {
|
2973
|
-
rb_raise(rb_ePGError, "write buffer zero string");
|
2974
|
-
}
|
2975
|
-
if((n = lo_write(conn, fd, StringValuePtr(buffer),
|
2976
|
-
RSTRING_LEN(buffer))) < 0) {
|
2977
|
-
rb_raise(rb_ePGError, "lo_write failed: %s", PQerrorMessage(conn));
|
2978
|
-
}
|
2979
|
-
|
2980
|
-
return INT2FIX(n);
|
2981
|
-
}
|
2982
|
-
|
2983
|
-
/*
|
2984
|
-
* call-seq:
|
2985
|
-
* conn.lo_read( lo_desc, len ) -> String
|
2986
|
-
*
|
2987
|
-
* Attempts to read _len_ bytes from large object _lo_desc_,
|
2988
|
-
* returns resulting data.
|
2989
|
-
*/
|
2990
|
-
static VALUE
|
2991
|
-
pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
2992
|
-
{
|
2993
|
-
int ret;
|
2994
|
-
PGconn *conn = get_pgconn(self);
|
2995
|
-
int len = NUM2INT(in_len);
|
2996
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
2997
|
-
VALUE str;
|
2998
|
-
char *buffer;
|
2999
|
-
|
3000
|
-
buffer = ALLOC_N(char, len);
|
3001
|
-
if(buffer == NULL)
|
3002
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
3003
|
-
|
3004
|
-
if (len < 0){
|
3005
|
-
rb_raise(rb_ePGError,"nagative length %d given", len);
|
3006
|
-
}
|
3007
|
-
|
3008
|
-
if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
|
3009
|
-
rb_raise(rb_ePGError, "lo_read failed");
|
3010
|
-
|
3011
|
-
if(ret == 0) {
|
3012
|
-
xfree(buffer);
|
3013
|
-
return Qnil;
|
3014
|
-
}
|
3015
|
-
|
3016
|
-
str = rb_tainted_str_new(buffer, ret);
|
3017
|
-
xfree(buffer);
|
3018
|
-
|
3019
|
-
return str;
|
3020
|
-
}
|
3021
|
-
|
3022
|
-
|
3023
|
-
/*
|
3024
|
-
* call-seq:
|
3025
|
-
* conn.lo_lseek( lo_desc, offset, whence ) -> Fixnum
|
3026
|
-
*
|
3027
|
-
* Move the large object pointer _lo_desc_ to offset _offset_.
|
3028
|
-
* Valid values for _whence_ are +SEEK_SET+, +SEEK_CUR+, and +SEEK_END+.
|
3029
|
-
* (Or 0, 1, or 2.)
|
3030
|
-
*/
|
3031
|
-
static VALUE
|
3032
|
-
pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
3033
|
-
{
|
3034
|
-
PGconn *conn = get_pgconn(self);
|
3035
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3036
|
-
int ret;
|
3037
|
-
|
3038
|
-
if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
|
3039
|
-
rb_raise(rb_ePGError, "lo_lseek failed");
|
3040
|
-
}
|
3041
|
-
|
3042
|
-
return INT2FIX(ret);
|
3043
|
-
}
|
3044
|
-
|
3045
|
-
/*
|
3046
|
-
* call-seq:
|
3047
|
-
* conn.lo_tell( lo_desc ) -> Fixnum
|
3048
|
-
*
|
3049
|
-
* Returns the current position of the large object _lo_desc_.
|
3050
|
-
*/
|
3051
|
-
static VALUE
|
3052
|
-
pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
3053
|
-
{
|
3054
|
-
int position;
|
3055
|
-
PGconn *conn = get_pgconn(self);
|
3056
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3057
|
-
|
3058
|
-
if((position = lo_tell(conn, lo_desc)) < 0)
|
3059
|
-
rb_raise(rb_ePGError,"lo_tell failed");
|
3060
|
-
|
3061
|
-
return INT2FIX(position);
|
3062
|
-
}
|
3063
|
-
|
3064
|
-
/*
|
3065
|
-
* call-seq:
|
3066
|
-
* conn.lo_truncate( lo_desc, len ) -> nil
|
3067
|
-
*
|
3068
|
-
* Truncates the large object _lo_desc_ to size _len_.
|
3069
|
-
*/
|
3070
|
-
static VALUE
|
3071
|
-
pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
3072
|
-
{
|
3073
|
-
PGconn *conn = get_pgconn(self);
|
3074
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3075
|
-
size_t len = NUM2INT(in_len);
|
3076
|
-
|
3077
|
-
if(lo_truncate(conn,lo_desc,len) < 0)
|
3078
|
-
rb_raise(rb_ePGError,"lo_truncate failed");
|
3079
|
-
|
3080
|
-
return Qnil;
|
3081
|
-
}
|
3082
|
-
|
3083
|
-
/*
|
3084
|
-
* call-seq:
|
3085
|
-
* conn.lo_close( lo_desc ) -> nil
|
3086
|
-
*
|
3087
|
-
* Closes the postgres large object of _lo_desc_.
|
3088
|
-
*/
|
3089
|
-
static VALUE
|
3090
|
-
pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
3091
|
-
{
|
3092
|
-
PGconn *conn = get_pgconn(self);
|
3093
|
-
int lo_desc = NUM2INT(in_lo_desc);
|
3094
|
-
|
3095
|
-
if(lo_close(conn,lo_desc) < 0)
|
3096
|
-
rb_raise(rb_ePGError,"lo_close failed");
|
3097
|
-
|
3098
|
-
return Qnil;
|
3099
|
-
}
|
3100
|
-
|
3101
|
-
/*
|
3102
|
-
* call-seq:
|
3103
|
-
* conn.lo_unlink( oid ) -> nil
|
3104
|
-
*
|
3105
|
-
* Unlinks (deletes) the postgres large object of _oid_.
|
3106
|
-
*/
|
3107
|
-
static VALUE
|
3108
|
-
pgconn_lounlink(VALUE self, VALUE in_oid)
|
3109
|
-
{
|
3110
|
-
PGconn *conn = get_pgconn(self);
|
3111
|
-
int oid = NUM2INT(in_oid);
|
3112
|
-
|
3113
|
-
if (oid < 0)
|
3114
|
-
rb_raise(rb_ePGError, "invalid oid %d",oid);
|
3115
|
-
|
3116
|
-
if(lo_unlink(conn,oid) < 0)
|
3117
|
-
rb_raise(rb_ePGError,"lo_unlink failed");
|
3118
|
-
|
3119
|
-
return Qnil;
|
3120
|
-
}
|
3121
|
-
|
3122
|
-
/********************************************************************
|
3123
|
-
*
|
3124
|
-
* Document-class: PGresult
|
3125
|
-
*
|
3126
|
-
* The class to represent the query result tuples (rows).
|
3127
|
-
* An instance of this class is created as the result of every query.
|
3128
|
-
* You may need to invoke the #clear method of the instance when finished with
|
3129
|
-
* the result for better memory performance.
|
3130
|
-
*
|
3131
|
-
* Example:
|
3132
|
-
* require 'pg'
|
3133
|
-
* conn = PGconn.open(:dbname => 'test')
|
3134
|
-
* res = conn.exec('SELECT 1 AS a, 2 AS b, NULL AS c')
|
3135
|
-
* res.getvalue(0,0) # '1'
|
3136
|
-
* res[0]['b'] # '2'
|
3137
|
-
* res[0]['c'] # nil
|
3138
|
-
*
|
3139
|
-
*/
|
3140
|
-
|
3141
|
-
/**************************************************************************
|
3142
|
-
* PGresult INSTANCE METHODS
|
3143
|
-
**************************************************************************/
|
3144
|
-
|
3145
|
-
/*
|
3146
|
-
* call-seq:
|
3147
|
-
* res.result_status() -> Fixnum
|
3148
|
-
*
|
3149
|
-
* Returns the status of the query. The status value is one of:
|
3150
|
-
* * +PGRES_EMPTY_QUERY+
|
3151
|
-
* * +PGRES_COMMAND_OK+
|
3152
|
-
* * +PGRES_TUPLES_OK+
|
3153
|
-
* * +PGRES_COPY_OUT+
|
3154
|
-
* * +PGRES_COPY_IN+
|
3155
|
-
* * +PGRES_BAD_RESPONSE+
|
3156
|
-
* * +PGRES_NONFATAL_ERROR+
|
3157
|
-
* * +PGRES_FATAL_ERROR+
|
3158
|
-
*/
|
3159
|
-
static VALUE
|
3160
|
-
pgresult_result_status(VALUE self)
|
3161
|
-
{
|
3162
|
-
return INT2FIX(PQresultStatus(get_pgresult(self)));
|
3163
|
-
}
|
3164
|
-
|
3165
|
-
/*
|
3166
|
-
* call-seq:
|
3167
|
-
* res.res_status( status ) -> String
|
3168
|
-
*
|
3169
|
-
* Returns the string representation of status +status+.
|
3170
|
-
*
|
3171
|
-
*/
|
3172
|
-
static VALUE
|
3173
|
-
pgresult_res_status(VALUE self, VALUE status)
|
3174
|
-
{
|
3175
|
-
VALUE ret = rb_tainted_str_new2(PQresStatus(NUM2INT(status)));
|
3176
|
-
ASSOCIATE_INDEX(ret, self);
|
3177
|
-
return ret;
|
3178
|
-
}
|
3179
|
-
|
3180
|
-
/*
|
3181
|
-
* call-seq:
|
3182
|
-
* res.error_message() -> String
|
3183
|
-
*
|
3184
|
-
* Returns the error message of the command as a string.
|
3185
|
-
*/
|
3186
|
-
static VALUE
|
3187
|
-
pgresult_error_message(VALUE self)
|
3188
|
-
{
|
3189
|
-
VALUE ret = rb_tainted_str_new2(PQresultErrorMessage(get_pgresult(self)));
|
3190
|
-
ASSOCIATE_INDEX(ret, self);
|
3191
|
-
return ret;
|
3192
|
-
}
|
3193
|
-
|
3194
|
-
/*
|
3195
|
-
* call-seq:
|
3196
|
-
* res.error_field(fieldcode) -> String
|
3197
|
-
*
|
3198
|
-
* Returns the individual field of an error.
|
3199
|
-
*
|
3200
|
-
* +fieldcode+ is one of:
|
3201
|
-
* * +PG_DIAG_SEVERITY+
|
3202
|
-
* * +PG_DIAG_SQLSTATE+
|
3203
|
-
* * +PG_DIAG_MESSAGE_PRIMARY+
|
3204
|
-
* * +PG_DIAG_MESSAGE_DETAIL+
|
3205
|
-
* * +PG_DIAG_MESSAGE_HINT+
|
3206
|
-
* * +PG_DIAG_STATEMENT_POSITION+
|
3207
|
-
* * +PG_DIAG_INTERNAL_POSITION+
|
3208
|
-
* * +PG_DIAG_INTERNAL_QUERY+
|
3209
|
-
* * +PG_DIAG_CONTEXT+
|
3210
|
-
* * +PG_DIAG_SOURCE_FILE+
|
3211
|
-
* * +PG_DIAG_SOURCE_LINE+
|
3212
|
-
* * +PG_DIAG_SOURCE_FUNCTION+
|
3213
|
-
*
|
3214
|
-
* An example:
|
3215
|
-
*
|
3216
|
-
* begin
|
3217
|
-
* conn.exec( "SELECT * FROM nonexistant_table" )
|
3218
|
-
* rescue PGError => err
|
3219
|
-
* p [
|
3220
|
-
* result.error_field( PGresult::PG_DIAG_SEVERITY ),
|
3221
|
-
* result.error_field( PGresult::PG_DIAG_SQLSTATE ),
|
3222
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_PRIMARY ),
|
3223
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_DETAIL ),
|
3224
|
-
* result.error_field( PGresult::PG_DIAG_MESSAGE_HINT ),
|
3225
|
-
* result.error_field( PGresult::PG_DIAG_STATEMENT_POSITION ),
|
3226
|
-
* result.error_field( PGresult::PG_DIAG_INTERNAL_POSITION ),
|
3227
|
-
* result.error_field( PGresult::PG_DIAG_INTERNAL_QUERY ),
|
3228
|
-
* result.error_field( PGresult::PG_DIAG_CONTEXT ),
|
3229
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_FILE ),
|
3230
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_LINE ),
|
3231
|
-
* result.error_field( PGresult::PG_DIAG_SOURCE_FUNCTION ),
|
3232
|
-
* ]
|
3233
|
-
* end
|
3234
|
-
*
|
3235
|
-
* Outputs:
|
3236
|
-
*
|
3237
|
-
* ["ERROR", "42P01", "relation \"nonexistant_table\" does not exist", nil, nil,
|
3238
|
-
* "15", nil, nil, nil, "path/to/parse_relation.c", "857", "parserOpenTable"]
|
3239
|
-
*/
|
3240
|
-
static VALUE
|
3241
|
-
pgresult_error_field(VALUE self, VALUE field)
|
3242
|
-
{
|
3243
|
-
PGresult *result = get_pgresult( self );
|
3244
|
-
int fieldcode = NUM2INT( field );
|
3245
|
-
char * fieldstr = PQresultErrorField( result, fieldcode );
|
3246
|
-
VALUE ret = Qnil;
|
3247
|
-
|
3248
|
-
if ( fieldstr ) {
|
3249
|
-
ret = rb_tainted_str_new2( fieldstr );
|
3250
|
-
ASSOCIATE_INDEX( ret, self );
|
3251
|
-
}
|
3252
|
-
|
3253
|
-
return ret;
|
3254
|
-
}
|
3255
|
-
|
3256
|
-
/*
|
3257
|
-
* call-seq:
|
3258
|
-
* res.clear() -> nil
|
3259
|
-
*
|
3260
|
-
* Clears the PGresult object as the result of the query.
|
3261
|
-
*/
|
3262
|
-
static VALUE
|
3263
|
-
pgresult_clear(VALUE self)
|
3264
|
-
{
|
3265
|
-
PQclear(get_pgresult(self));
|
3266
|
-
DATA_PTR(self) = NULL;
|
3267
|
-
return Qnil;
|
3268
|
-
}
|
3269
|
-
|
3270
|
-
/*
|
3271
|
-
* call-seq:
|
3272
|
-
* res.ntuples() -> Fixnum
|
3273
|
-
*
|
3274
|
-
* Returns the number of tuples in the query result.
|
3275
|
-
*/
|
3276
|
-
static VALUE
|
3277
|
-
pgresult_ntuples(VALUE self)
|
3278
|
-
{
|
3279
|
-
return INT2FIX(PQntuples(get_pgresult(self)));
|
3280
|
-
}
|
3281
|
-
|
3282
|
-
/*
|
3283
|
-
* call-seq:
|
3284
|
-
* res.nfields() -> Fixnum
|
3285
|
-
*
|
3286
|
-
* Returns the number of columns in the query result.
|
3287
|
-
*/
|
3288
|
-
static VALUE
|
3289
|
-
pgresult_nfields(VALUE self)
|
3290
|
-
{
|
3291
|
-
return INT2NUM(PQnfields(get_pgresult(self)));
|
3292
|
-
}
|
3293
|
-
|
3294
|
-
/*
|
3295
|
-
* call-seq:
|
3296
|
-
* res.fname( index ) -> String
|
3297
|
-
*
|
3298
|
-
* Returns the name of the column corresponding to _index_.
|
3299
|
-
*/
|
3300
|
-
static VALUE
|
3301
|
-
pgresult_fname(VALUE self, VALUE index)
|
3302
|
-
{
|
3303
|
-
VALUE fname;
|
3304
|
-
PGresult *result;
|
3305
|
-
int i = NUM2INT(index);
|
3306
|
-
|
3307
|
-
result = get_pgresult(self);
|
3308
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3309
|
-
rb_raise(rb_eArgError,"invalid field number %d", i);
|
3310
|
-
}
|
3311
|
-
fname = rb_tainted_str_new2(PQfname(result, i));
|
3312
|
-
ASSOCIATE_INDEX(fname, self);
|
3313
|
-
return fname;
|
3314
|
-
}
|
3315
|
-
|
3316
|
-
/*
|
3317
|
-
* call-seq:
|
3318
|
-
* res.fnumber( name ) -> Fixnum
|
3319
|
-
*
|
3320
|
-
* Returns the index of the field specified by the string _name_.
|
3321
|
-
*
|
3322
|
-
* Raises an ArgumentError if the specified _name_ isn't one of the field names;
|
3323
|
-
* raises a TypeError if _name_ is not a String.
|
3324
|
-
*/
|
3325
|
-
static VALUE
|
3326
|
-
pgresult_fnumber(VALUE self, VALUE name)
|
3327
|
-
{
|
3328
|
-
int n;
|
3329
|
-
|
3330
|
-
Check_Type(name, T_STRING);
|
3331
|
-
|
3332
|
-
n = PQfnumber(get_pgresult(self), StringValuePtr(name));
|
3333
|
-
if (n == -1) {
|
3334
|
-
rb_raise(rb_eArgError,"Unknown field: %s", StringValuePtr(name));
|
3335
|
-
}
|
3336
|
-
return INT2FIX(n);
|
3337
|
-
}
|
3338
|
-
|
3339
|
-
/*
|
3340
|
-
* call-seq:
|
3341
|
-
* res.ftable( column_number ) -> Fixnum
|
3342
|
-
*
|
3343
|
-
* Returns the Oid of the table from which the column _column_number_
|
3344
|
-
* was fetched.
|
3345
|
-
*
|
3346
|
-
* Raises ArgumentError if _column_number_ is out of range or if
|
3347
|
-
* the Oid is undefined for that column.
|
3348
|
-
*/
|
3349
|
-
static VALUE
|
3350
|
-
pgresult_ftable(VALUE self, VALUE column_number)
|
3351
|
-
{
|
3352
|
-
Oid n ;
|
3353
|
-
int col_number = NUM2INT(column_number);
|
3354
|
-
PGresult *pgresult = get_pgresult(self);
|
3355
|
-
|
3356
|
-
if( col_number < 0 || col_number >= PQnfields(pgresult))
|
3357
|
-
rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
|
3358
|
-
|
3359
|
-
n = PQftable(pgresult, col_number);
|
3360
|
-
return INT2FIX(n);
|
3361
|
-
}
|
3362
|
-
|
3363
|
-
/*
|
3364
|
-
* call-seq:
|
3365
|
-
* res.ftablecol( column_number ) -> Fixnum
|
3366
|
-
*
|
3367
|
-
* Returns the column number (within its table) of the table from
|
3368
|
-
* which the column _column_number_ is made up.
|
3369
|
-
*
|
3370
|
-
* Raises ArgumentError if _column_number_ is out of range or if
|
3371
|
-
* the column number from its table is undefined for that column.
|
3372
|
-
*/
|
3373
|
-
static VALUE
|
3374
|
-
pgresult_ftablecol(VALUE self, VALUE column_number)
|
3375
|
-
{
|
3376
|
-
int col_number = NUM2INT(column_number);
|
3377
|
-
PGresult *pgresult = get_pgresult(self);
|
3378
|
-
|
3379
|
-
int n;
|
3380
|
-
|
3381
|
-
if( col_number < 0 || col_number >= PQnfields(pgresult))
|
3382
|
-
rb_raise(rb_eArgError,"Invalid column index: %d", col_number);
|
3383
|
-
|
3384
|
-
n = PQftablecol(pgresult, col_number);
|
3385
|
-
return INT2FIX(n);
|
3386
|
-
}
|
3387
|
-
|
3388
|
-
/*
|
3389
|
-
* call-seq:
|
3390
|
-
* res.fformat( column_number ) -> Fixnum
|
3391
|
-
*
|
3392
|
-
* Returns the format (0 for text, 1 for binary) of column
|
3393
|
-
* _column_number_.
|
3394
|
-
*
|
3395
|
-
* Raises ArgumentError if _column_number_ is out of range.
|
3396
|
-
*/
|
3397
|
-
static VALUE
|
3398
|
-
pgresult_fformat(VALUE self, VALUE column_number)
|
3399
|
-
{
|
3400
|
-
PGresult *result = get_pgresult(self);
|
3401
|
-
int fnumber = NUM2INT(column_number);
|
3402
|
-
if (fnumber < 0 || fnumber >= PQnfields(result)) {
|
3403
|
-
rb_raise(rb_eArgError, "Column number is out of range: %d",
|
3404
|
-
fnumber);
|
3405
|
-
}
|
3406
|
-
return INT2FIX(PQfformat(result, fnumber));
|
3407
|
-
}
|
3408
|
-
|
3409
|
-
/*
|
3410
|
-
* call-seq:
|
3411
|
-
* res.ftype( column_number )
|
3412
|
-
*
|
3413
|
-
* Returns the data type associated with _column_number_.
|
3414
|
-
*
|
3415
|
-
* The integer returned is the internal +OID+ number (in PostgreSQL)
|
3416
|
-
* of the type. To get a human-readable value for the type, use the
|
3417
|
-
* returned OID and the field's #fmod value with the format_type() SQL
|
3418
|
-
* function:
|
3419
|
-
*
|
3420
|
-
* # Get the type of the second column of the result 'res'
|
3421
|
-
* typename = conn.
|
3422
|
-
* exec( "SELECT format_type($1,$2)", [res.ftype(1), res.fmod(1)] ).
|
3423
|
-
* getvalue( 0, 0 )
|
3424
|
-
*
|
3425
|
-
* Raises an ArgumentError if _column_number_ is out of range.
|
3426
|
-
*/
|
3427
|
-
static VALUE
|
3428
|
-
pgresult_ftype(VALUE self, VALUE index)
|
3429
|
-
{
|
3430
|
-
PGresult* result = get_pgresult(self);
|
3431
|
-
int i = NUM2INT(index);
|
3432
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3433
|
-
rb_raise(rb_eArgError, "invalid field number %d", i);
|
3434
|
-
}
|
3435
|
-
return INT2NUM(PQftype(result, i));
|
3436
|
-
}
|
3437
|
-
|
3438
|
-
/*
|
3439
|
-
* call-seq:
|
3440
|
-
* res.fmod( column_number )
|
3441
|
-
*
|
3442
|
-
* Returns the type modifier associated with column _column_number_. See
|
3443
|
-
* the #ftype method for an example of how to use this.
|
3444
|
-
*
|
3445
|
-
* Raises an ArgumentError if _column_number_ is out of range.
|
3446
|
-
*/
|
3447
|
-
static VALUE
|
3448
|
-
pgresult_fmod(VALUE self, VALUE column_number)
|
3449
|
-
{
|
3450
|
-
PGresult *result = get_pgresult(self);
|
3451
|
-
int fnumber = NUM2INT(column_number);
|
3452
|
-
int modifier;
|
3453
|
-
if (fnumber < 0 || fnumber >= PQnfields(result)) {
|
3454
|
-
rb_raise(rb_eArgError, "Column number is out of range: %d",
|
3455
|
-
fnumber);
|
3456
|
-
}
|
3457
|
-
modifier = PQfmod(result,fnumber);
|
3458
|
-
|
3459
|
-
return INT2NUM(modifier);
|
3460
|
-
}
|
3461
|
-
|
3462
|
-
/*
|
3463
|
-
* call-seq:
|
3464
|
-
* res.fsize( index )
|
3465
|
-
*
|
3466
|
-
* Returns the size of the field type in bytes. Returns <tt>-1</tt> if the field is variable sized.
|
3467
|
-
*
|
3468
|
-
* res = conn.exec("SELECT myInt, myVarChar50 FROM foo")
|
3469
|
-
* res.size(0) => 4
|
3470
|
-
* res.size(1) => -1
|
3471
|
-
*/
|
3472
|
-
static VALUE
|
3473
|
-
pgresult_fsize(VALUE self, VALUE index)
|
3474
|
-
{
|
3475
|
-
PGresult *result;
|
3476
|
-
int i = NUM2INT(index);
|
3477
|
-
|
3478
|
-
result = get_pgresult(self);
|
3479
|
-
if (i < 0 || i >= PQnfields(result)) {
|
3480
|
-
rb_raise(rb_eArgError,"invalid field number %d", i);
|
3481
|
-
}
|
3482
|
-
return INT2NUM(PQfsize(result, i));
|
3483
|
-
}
|
3484
|
-
|
3485
|
-
/*
|
3486
|
-
* call-seq:
|
3487
|
-
* res.getvalue( tup_num, field_num )
|
3488
|
-
*
|
3489
|
-
* Returns the value in tuple number _tup_num_, field _field_num_,
|
3490
|
-
* or +nil+ if the field is +NULL+.
|
3491
|
-
*/
|
3492
|
-
static VALUE
|
3493
|
-
pgresult_getvalue(VALUE self, VALUE tup_num, VALUE field_num)
|
3494
|
-
{
|
3495
|
-
VALUE ret;
|
3496
|
-
PGresult *result;
|
3497
|
-
int i = NUM2INT(tup_num);
|
3498
|
-
int j = NUM2INT(field_num);
|
3499
|
-
|
3500
|
-
result = get_pgresult(self);
|
3501
|
-
if(i < 0 || i >= PQntuples(result)) {
|
3502
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3503
|
-
}
|
3504
|
-
if(j < 0 || j >= PQnfields(result)) {
|
3505
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3506
|
-
}
|
3507
|
-
if(PQgetisnull(result, i, j))
|
3508
|
-
return Qnil;
|
3509
|
-
ret = rb_tainted_str_new(PQgetvalue(result, i, j),
|
3510
|
-
PQgetlength(result, i, j));
|
3511
|
-
ASSOCIATE_INDEX(ret, self);
|
3512
|
-
return ret;
|
3513
|
-
}
|
3514
|
-
|
3515
|
-
/*
|
3516
|
-
* call-seq:
|
3517
|
-
* res.getisnull(tuple_position, field_position) -> boolean
|
3518
|
-
*
|
3519
|
-
* Returns +true+ if the specified value is +nil+; +false+ otherwise.
|
3520
|
-
*/
|
3521
|
-
static VALUE
|
3522
|
-
pgresult_getisnull(VALUE self, VALUE tup_num, VALUE field_num)
|
3523
|
-
{
|
3524
|
-
PGresult *result;
|
3525
|
-
int i = NUM2INT(tup_num);
|
3526
|
-
int j = NUM2INT(field_num);
|
3527
|
-
|
3528
|
-
result = get_pgresult(self);
|
3529
|
-
if (i < 0 || i >= PQntuples(result)) {
|
3530
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3531
|
-
}
|
3532
|
-
if (j < 0 || j >= PQnfields(result)) {
|
3533
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3534
|
-
}
|
3535
|
-
return PQgetisnull(result, i, j) ? Qtrue : Qfalse;
|
3536
|
-
}
|
3537
|
-
|
3538
1
|
/*
|
3539
|
-
*
|
3540
|
-
*
|
2
|
+
* pg.c - Toplevel extension
|
3
|
+
* $Id: pg.c,v 1cdad2ce8993 2012/01/25 01:21:30 ged $
|
3541
4
|
*
|
3542
|
-
*
|
5
|
+
* Author/s:
|
3543
6
|
*
|
3544
|
-
*
|
3545
|
-
|
3546
|
-
|
3547
|
-
|
3548
|
-
|
3549
|
-
|
3550
|
-
|
3551
|
-
int j = NUM2INT(field_num);
|
3552
|
-
|
3553
|
-
result = get_pgresult(self);
|
3554
|
-
if (i < 0 || i >= PQntuples(result)) {
|
3555
|
-
rb_raise(rb_eArgError,"invalid tuple number %d", i);
|
3556
|
-
}
|
3557
|
-
if (j < 0 || j >= PQnfields(result)) {
|
3558
|
-
rb_raise(rb_eArgError,"invalid field number %d", j);
|
3559
|
-
}
|
3560
|
-
return INT2FIX(PQgetlength(result, i, j));
|
3561
|
-
}
|
3562
|
-
|
3563
|
-
/*
|
3564
|
-
* call-seq:
|
3565
|
-
* res.nparams() -> Fixnum
|
7
|
+
* - Jeff Davis <ruby-pg@j-davis.com>
|
8
|
+
* - Guy Decoux (ts) <decoux@moulon.inra.fr>
|
9
|
+
* - Michael Granger <ged@FaerieMUD.org>
|
10
|
+
* - Dave Lee
|
11
|
+
* - Eiji Matsumoto <usagi@ruby.club.or.jp>
|
12
|
+
* - Yukihiro Matsumoto <matz@ruby-lang.org>
|
13
|
+
* - Noboru Saitou <noborus@netlab.jp>
|
3566
14
|
*
|
3567
|
-
*
|
3568
|
-
*
|
3569
|
-
*/
|
3570
|
-
static VALUE
|
3571
|
-
pgresult_nparams(VALUE self)
|
3572
|
-
{
|
3573
|
-
PGresult *result;
|
3574
|
-
|
3575
|
-
result = get_pgresult(self);
|
3576
|
-
return INT2FIX(PQnparams(result));
|
3577
|
-
}
|
3578
|
-
|
3579
|
-
/*
|
3580
|
-
* call-seq:
|
3581
|
-
* res.paramtype( param_number ) -> Oid
|
15
|
+
* See Contributors.rdoc for the many additional fine people that have contributed
|
16
|
+
* to this library over the years.
|
3582
17
|
*
|
3583
|
-
*
|
3584
|
-
* Only useful for the result returned by conn.describePrepared
|
3585
|
-
*/
|
3586
|
-
static VALUE
|
3587
|
-
pgresult_paramtype(VALUE self, VALUE param_number)
|
3588
|
-
{
|
3589
|
-
PGresult *result;
|
3590
|
-
|
3591
|
-
result = get_pgresult(self);
|
3592
|
-
return INT2FIX(PQparamtype(result,NUM2INT(param_number)));
|
3593
|
-
}
|
3594
|
-
|
3595
|
-
/*
|
3596
|
-
* call-seq:
|
3597
|
-
* res.cmd_status() -> String
|
18
|
+
* Copyright (c) 1997-2012 by the authors.
|
3598
19
|
*
|
3599
|
-
*
|
3600
|
-
|
3601
|
-
|
3602
|
-
pgresult_cmd_status(VALUE self)
|
3603
|
-
{
|
3604
|
-
VALUE ret = rb_tainted_str_new2(PQcmdStatus(get_pgresult(self)));
|
3605
|
-
ASSOCIATE_INDEX(ret, self);
|
3606
|
-
return ret;
|
3607
|
-
}
|
3608
|
-
|
3609
|
-
/*
|
3610
|
-
* call-seq:
|
3611
|
-
* res.cmd_tuples() -> Fixnum
|
20
|
+
* You may redistribute this software under the same terms as Ruby itself; see
|
21
|
+
* http://www.ruby-lang.org/en/LICENSE.txt or the LICENSE file in the source
|
22
|
+
* for details.
|
3612
23
|
*
|
3613
|
-
*
|
24
|
+
* Portions of the code are from the PostgreSQL project, and are distributed
|
25
|
+
* under the terms of the PostgreSQL license, included in the file "POSTGRES".
|
3614
26
|
*
|
3615
|
-
*
|
3616
|
-
* * +INSERT+
|
3617
|
-
* * +UPDATE+
|
3618
|
-
* * +DELETE+
|
3619
|
-
* * +MOVE+
|
3620
|
-
* * +FETCH+
|
3621
|
-
* or if no tuples were affected, <tt>0</tt> is returned.
|
3622
|
-
*/
|
3623
|
-
static VALUE
|
3624
|
-
pgresult_cmd_tuples(VALUE self)
|
3625
|
-
{
|
3626
|
-
long n;
|
3627
|
-
n = strtol(PQcmdTuples(get_pgresult(self)),NULL, 10);
|
3628
|
-
return INT2NUM(n);
|
3629
|
-
}
|
3630
|
-
|
3631
|
-
/*
|
3632
|
-
* call-seq:
|
3633
|
-
* res.oid_value() -> Fixnum
|
27
|
+
* Portions copyright LAIKA, Inc.
|
3634
28
|
*
|
3635
|
-
* Returns the +oid+ of the inserted row if applicable,
|
3636
|
-
* otherwise +nil+.
|
3637
|
-
*/
|
3638
|
-
static VALUE
|
3639
|
-
pgresult_oid_value(VALUE self)
|
3640
|
-
{
|
3641
|
-
Oid n = PQoidValue(get_pgresult(self));
|
3642
|
-
if (n == InvalidOid)
|
3643
|
-
return Qnil;
|
3644
|
-
else
|
3645
|
-
return INT2FIX(n);
|
3646
|
-
}
|
3647
|
-
|
3648
|
-
/* Utility methods not in libpq */
|
3649
|
-
|
3650
|
-
/*
|
3651
|
-
* call-seq:
|
3652
|
-
* res[ n ] -> Hash
|
3653
29
|
*
|
3654
|
-
*
|
3655
|
-
|
3656
|
-
static VALUE
|
3657
|
-
pgresult_aref(VALUE self, VALUE index)
|
3658
|
-
{
|
3659
|
-
PGresult *result = get_pgresult(self);
|
3660
|
-
int tuple_num = NUM2INT(index);
|
3661
|
-
int field_num;
|
3662
|
-
VALUE fname,val;
|
3663
|
-
VALUE tuple;
|
3664
|
-
|
3665
|
-
if ( tuple_num < 0 || tuple_num >= PQntuples(result) )
|
3666
|
-
rb_raise( rb_eIndexError, "Index %d is out of range", tuple_num );
|
3667
|
-
|
3668
|
-
tuple = rb_hash_new();
|
3669
|
-
for ( field_num = 0; field_num < PQnfields(result); field_num++ ) {
|
3670
|
-
fname = rb_tainted_str_new2( PQfname(result,field_num) );
|
3671
|
-
ASSOCIATE_INDEX(fname, self);
|
3672
|
-
if ( PQgetisnull(result, tuple_num, field_num) ) {
|
3673
|
-
rb_hash_aset( tuple, fname, Qnil );
|
3674
|
-
}
|
3675
|
-
else {
|
3676
|
-
val = rb_tainted_str_new( PQgetvalue(result, tuple_num, field_num ),
|
3677
|
-
PQgetlength(result, tuple_num, field_num) );
|
3678
|
-
|
3679
|
-
/* associate client encoding for text format only */
|
3680
|
-
if ( 0 == PQfformat(result, field_num) ) {
|
3681
|
-
ASSOCIATE_INDEX( val, self );
|
3682
|
-
} else {
|
3683
|
-
#ifdef M17N_SUPPORTED
|
3684
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3685
|
-
#endif
|
3686
|
-
}
|
3687
|
-
rb_hash_aset( tuple, fname, val );
|
3688
|
-
}
|
3689
|
-
}
|
3690
|
-
return tuple;
|
3691
|
-
}
|
3692
|
-
|
3693
|
-
|
3694
|
-
/*
|
3695
|
-
* call-seq:
|
3696
|
-
* res.values -> Array
|
30
|
+
* The following functions are part of libpq, but not available from ruby-pg,
|
31
|
+
* because they are deprecated, obsolete, or generally not useful:
|
3697
32
|
*
|
3698
|
-
*
|
33
|
+
* - PQfreemem -- unnecessary: copied to ruby object, then freed. Ruby object's
|
34
|
+
* memory is freed when it is garbage collected.
|
35
|
+
* - PQbinaryTuples -- better to use PQfformat
|
36
|
+
* - PQprint -- not very useful
|
37
|
+
* - PQsetdb -- not very useful
|
38
|
+
* - PQoidStatus -- deprecated, use PQoidValue
|
39
|
+
* - PQrequestCancel -- deprecated, use PQcancel
|
40
|
+
* - PQfn -- use a prepared statement instead
|
41
|
+
* - PQgetline -- deprecated, use PQgetCopyData
|
42
|
+
* - PQgetlineAsync -- deprecated, use PQgetCopyData
|
43
|
+
* - PQputline -- deprecated, use PQputCopyData
|
44
|
+
* - PQputnbytes -- deprecated, use PQputCopyData
|
45
|
+
* - PQendcopy -- deprecated, use PQputCopyEnd
|
3699
46
|
*/
|
3700
|
-
static VALUE
|
3701
|
-
pgresult_values(VALUE self, VALUE index)
|
3702
|
-
{
|
3703
|
-
PGresult* result = (PGresult*) get_pgresult(self);
|
3704
|
-
int row;
|
3705
|
-
int field;
|
3706
|
-
int num_rows = PQntuples(result);
|
3707
|
-
int num_fields = PQnfields(result);
|
3708
|
-
VALUE ary = rb_ary_new2(num_rows);
|
3709
|
-
|
3710
|
-
for ( row = 0; row < num_rows; row++ ) {
|
3711
|
-
/* create new row */
|
3712
|
-
VALUE new_row = rb_ary_new2(num_fields);
|
3713
|
-
|
3714
|
-
/* add to return array */
|
3715
|
-
rb_ary_store( ary, row, new_row );
|
3716
|
-
|
3717
|
-
/* populate it */
|
3718
|
-
for ( field = 0; field < num_fields; field++ ) {
|
3719
|
-
if ( PQgetisnull(result, row, field) ) {
|
3720
|
-
rb_ary_store( new_row, field, Qnil );
|
3721
|
-
}
|
3722
|
-
else {
|
3723
|
-
VALUE val = rb_tainted_str_new( PQgetvalue(result, row, field),
|
3724
|
-
PQgetlength(result, row, field) );
|
3725
|
-
|
3726
|
-
/* associate client encoding for text format only */
|
3727
|
-
if ( 0 == PQfformat(result, field) ) {
|
3728
|
-
ASSOCIATE_INDEX( val, self );
|
3729
|
-
} else {
|
3730
|
-
#ifdef M17N_SUPPORTED
|
3731
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3732
|
-
#endif
|
3733
|
-
}
|
3734
|
-
|
3735
|
-
rb_ary_store( new_row, field, val );
|
3736
|
-
}
|
3737
|
-
}
|
3738
|
-
}
|
3739
|
-
return ary;
|
3740
|
-
}
|
3741
47
|
|
48
|
+
#include "pg.h"
|
3742
49
|
|
3743
|
-
|
3744
|
-
|
3745
|
-
|
3746
|
-
*
|
3747
|
-
* Returns an Array of the values from the nth column of each
|
3748
|
-
* tuple in the result.
|
3749
|
-
*
|
3750
|
-
*/
|
3751
|
-
static VALUE
|
3752
|
-
pgresult_column_values(VALUE self, VALUE index)
|
3753
|
-
{
|
3754
|
-
int col = NUM2INT( index );
|
3755
|
-
return make_column_result_array( self, col );
|
3756
|
-
}
|
50
|
+
VALUE rb_mPG;
|
51
|
+
VALUE rb_ePGerror;
|
52
|
+
VALUE rb_mPGconstants;
|
3757
53
|
|
3758
54
|
|
3759
55
|
/*
|
3760
|
-
*
|
3761
|
-
* res.field_values( field ) -> array
|
56
|
+
* Document-class: PGError
|
3762
57
|
*
|
3763
|
-
*
|
58
|
+
* This is the exception class raised when an error is returned from
|
59
|
+
* a libpq API call.
|
3764
60
|
*
|
3765
|
-
|
3766
|
-
|
3767
|
-
pgresult_field_values( VALUE self, VALUE field )
|
3768
|
-
{
|
3769
|
-
PGresult *result = get_pgresult( self );
|
3770
|
-
const char *fieldname = RSTRING_PTR( field );
|
3771
|
-
int fnum = PQfnumber( result, fieldname );
|
3772
|
-
|
3773
|
-
if ( fnum < 0 )
|
3774
|
-
rb_raise( rb_eIndexError, "no such field '%s' in result", fieldname );
|
3775
|
-
|
3776
|
-
return make_column_result_array( self, fnum );
|
3777
|
-
}
|
3778
|
-
|
3779
|
-
|
3780
|
-
/*
|
3781
|
-
* Make a Ruby array out of the encoded values from the specified
|
3782
|
-
* column in the given result.
|
3783
|
-
*/
|
3784
|
-
static VALUE
|
3785
|
-
make_column_result_array( VALUE self, int col )
|
3786
|
-
{
|
3787
|
-
PGresult *result = get_pgresult( self );
|
3788
|
-
int row = PQntuples( result );
|
3789
|
-
VALUE ary = rb_ary_new2( row );
|
3790
|
-
VALUE val = Qnil;
|
3791
|
-
|
3792
|
-
if ( col >= PQnfields(result) )
|
3793
|
-
rb_raise( rb_eIndexError, "no column %d in result", col );
|
3794
|
-
|
3795
|
-
while ( row-- ) {
|
3796
|
-
val = rb_tainted_str_new( PQgetvalue(result, row, col),
|
3797
|
-
PQgetlength(result, row, col) );
|
3798
|
-
|
3799
|
-
/* associate client encoding for text format only */
|
3800
|
-
if ( 0 == PQfformat(result, col) ) {
|
3801
|
-
ASSOCIATE_INDEX( val, self );
|
3802
|
-
} else {
|
3803
|
-
#ifdef M17N_SUPPORTED
|
3804
|
-
rb_enc_associate( val, rb_ascii8bit_encoding() );
|
3805
|
-
#endif
|
3806
|
-
}
|
3807
|
-
|
3808
|
-
rb_ary_store( ary, row, val );
|
3809
|
-
}
|
3810
|
-
|
3811
|
-
return ary;
|
3812
|
-
}
|
3813
|
-
|
3814
|
-
|
3815
|
-
/*
|
3816
|
-
* call-seq:
|
3817
|
-
* res.each{ |tuple| ... }
|
61
|
+
* The attributes +connection+ and +result+ are set to the connection
|
62
|
+
* object and result set object, respectively.
|
3818
63
|
*
|
3819
|
-
*
|
64
|
+
* If the connection object or result set object is not available from
|
65
|
+
* the context in which the error was encountered, it is +nil+.
|
3820
66
|
*/
|
3821
|
-
static VALUE
|
3822
|
-
pgresult_each(VALUE self)
|
3823
|
-
{
|
3824
|
-
PGresult *result = get_pgresult(self);
|
3825
|
-
int tuple_num;
|
3826
|
-
|
3827
|
-
for(tuple_num = 0; tuple_num < PQntuples(result); tuple_num++) {
|
3828
|
-
rb_yield(pgresult_aref(self, INT2NUM(tuple_num)));
|
3829
|
-
}
|
3830
|
-
return self;
|
3831
|
-
}
|
3832
67
|
|
3833
68
|
/*
|
3834
|
-
*
|
3835
|
-
* res.fields() -> Array
|
3836
|
-
*
|
3837
|
-
* Returns an array of Strings representing the names of the fields in the result.
|
69
|
+
* M17n functions
|
3838
70
|
*/
|
3839
|
-
static VALUE
|
3840
|
-
pgresult_fields(VALUE self)
|
3841
|
-
{
|
3842
|
-
PGresult *result;
|
3843
|
-
VALUE ary;
|
3844
|
-
int n, i;
|
3845
|
-
|
3846
|
-
result = get_pgresult(self);
|
3847
|
-
n = PQnfields(result);
|
3848
|
-
ary = rb_ary_new2(n);
|
3849
|
-
for (i=0;i<n;i++) {
|
3850
|
-
VALUE val = rb_tainted_str_new2(PQfname(result, i));
|
3851
|
-
ASSOCIATE_INDEX(val, self);
|
3852
|
-
rb_ary_push(ary, val);
|
3853
|
-
}
|
3854
|
-
return ary;
|
3855
|
-
}
|
3856
|
-
|
3857
71
|
|
3858
72
|
#ifdef M17N_SUPPORTED
|
3859
73
|
/**
|
3860
74
|
* The mapping from canonical encoding names in PostgreSQL to ones in Ruby.
|
3861
75
|
*/
|
3862
|
-
|
3863
|
-
|
3864
|
-
|
3865
|
-
|
3866
|
-
|
3867
|
-
|
3868
|
-
|
3869
|
-
|
3870
|
-
|
3871
|
-
|
3872
|
-
|
3873
|
-
|
3874
|
-
|
3875
|
-
|
3876
|
-
|
3877
|
-
|
3878
|
-
|
3879
|
-
|
3880
|
-
|
3881
|
-
|
3882
|
-
|
3883
|
-
|
3884
|
-
|
3885
|
-
|
3886
|
-
|
3887
|
-
|
3888
|
-
|
3889
|
-
|
3890
|
-
|
3891
|
-
|
3892
|
-
|
3893
|
-
|
3894
|
-
|
3895
|
-
|
3896
|
-
|
3897
|
-
|
3898
|
-
|
3899
|
-
|
3900
|
-
|
3901
|
-
|
3902
|
-
|
3903
|
-
|
3904
|
-
|
3905
|
-
|
76
|
+
const char * const (pg_enc_pg2ruby_mapping[][2]) = {
|
77
|
+
{"BIG5", "Big5" },
|
78
|
+
{"EUC_CN", "GB2312" },
|
79
|
+
{"EUC_JP", "EUC-JP" },
|
80
|
+
{"EUC_JIS_2004", "EUC-JP" },
|
81
|
+
{"EUC_KR", "EUC-KR" },
|
82
|
+
{"EUC_TW", "EUC-TW" },
|
83
|
+
{"GB18030", "GB18030" },
|
84
|
+
{"GBK", "GBK" },
|
85
|
+
{"ISO_8859_5", "ISO-8859-5" },
|
86
|
+
{"ISO_8859_6", "ISO-8859-6" },
|
87
|
+
{"ISO_8859_7", "ISO-8859-7" },
|
88
|
+
{"ISO_8859_8", "ISO-8859-8" },
|
89
|
+
/* {"JOHAB", "JOHAB" }, dummy */
|
90
|
+
{"KOI8", "KOI8-R" },
|
91
|
+
{"KOI8R", "KOI8-R" },
|
92
|
+
{"KOI8U", "KOI8-U" },
|
93
|
+
{"LATIN1", "ISO-8859-1" },
|
94
|
+
{"LATIN2", "ISO-8859-2" },
|
95
|
+
{"LATIN3", "ISO-8859-3" },
|
96
|
+
{"LATIN4", "ISO-8859-4" },
|
97
|
+
{"LATIN5", "ISO-8859-9" },
|
98
|
+
{"LATIN6", "ISO-8859-10" },
|
99
|
+
{"LATIN7", "ISO-8859-13" },
|
100
|
+
{"LATIN8", "ISO-8859-14" },
|
101
|
+
{"LATIN9", "ISO-8859-15" },
|
102
|
+
{"LATIN10", "ISO-8859-16" },
|
103
|
+
{"MULE_INTERNAL", "Emacs-Mule" },
|
104
|
+
{"SJIS", "Windows-31J" },
|
105
|
+
{"SHIFT_JIS_2004","Windows-31J" },
|
106
|
+
/* {"SQL_ASCII", NULL }, special case*/
|
107
|
+
{"UHC", "CP949" },
|
108
|
+
{"UTF8", "UTF-8" },
|
109
|
+
{"WIN866", "IBM866" },
|
110
|
+
{"WIN874", "Windows-874" },
|
111
|
+
{"WIN1250", "Windows-1250"},
|
112
|
+
{"WIN1251", "Windows-1251"},
|
113
|
+
{"WIN1252", "Windows-1252"},
|
114
|
+
{"WIN1253", "Windows-1253"},
|
115
|
+
{"WIN1254", "Windows-1254"},
|
116
|
+
{"WIN1255", "Windows-1255"},
|
117
|
+
{"WIN1256", "Windows-1256"},
|
118
|
+
{"WIN1257", "Windows-1257"},
|
119
|
+
{"WIN1258", "Windows-1258"}
|
3906
120
|
};
|
3907
121
|
|
3908
122
|
|
@@ -3912,7 +126,14 @@ static const char * const (enc_pg2ruby_mapping[][2]) = {
|
|
3912
126
|
static struct st_table *enc_pg2ruby;
|
3913
127
|
static ID s_id_index;
|
3914
128
|
|
3915
|
-
|
129
|
+
|
130
|
+
/*
|
131
|
+
* Get the index of encoding +val+.
|
132
|
+
* :FIXME: Look into replacing this with rb_enc_get_index() since 1.9.1 isn't really
|
133
|
+
* used anymore.
|
134
|
+
*/
|
135
|
+
int
|
136
|
+
pg_enc_get_index(VALUE val)
|
3916
137
|
{
|
3917
138
|
int i = ENCODING_GET_INLINED(val);
|
3918
139
|
if (i == ENCODING_INLINE_MAX) {
|
@@ -3922,21 +143,18 @@ static int enc_get_index(VALUE val)
|
|
3922
143
|
return i;
|
3923
144
|
}
|
3924
145
|
|
3925
|
-
#ifdef HAVE_RB_ENCDB_ALIAS
|
3926
|
-
# define ENC_ALIAS(name, orig) rb_encdb_alias((name), (orig))
|
3927
|
-
#elif HAVE_RB_ENC_ALIAS
|
3928
|
-
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
|
3929
|
-
#else
|
3930
|
-
extern int rb_enc_alias(const char *alias, const char *orig); /* declaration missing in Ruby 1.9.1 */
|
3931
|
-
# define ENC_ALIAS(name, orig) rb_enc_alias((name), (orig))
|
3932
|
-
#endif
|
3933
146
|
|
147
|
+
/*
|
148
|
+
* Look up the JOHAB encoding, creating it as a dummy encoding if it's not
|
149
|
+
* already defined.
|
150
|
+
*/
|
3934
151
|
static rb_encoding *
|
3935
|
-
|
152
|
+
pg_find_or_create_johab(void)
|
3936
153
|
{
|
3937
154
|
static const char * const aliases[] = { "JOHAB", "Windows-1361", "CP1361" };
|
3938
155
|
int enc_index;
|
3939
|
-
|
156
|
+
size_t i;
|
157
|
+
|
3940
158
|
for (i = 0; i < sizeof(aliases)/sizeof(aliases[0]); ++i) {
|
3941
159
|
enc_index = rb_enc_find_index(aliases[i]);
|
3942
160
|
if (enc_index > 0) return rb_enc_from_index(enc_index);
|
@@ -3950,465 +168,200 @@ find_or_create_johab(void)
|
|
3950
168
|
}
|
3951
169
|
|
3952
170
|
/*
|
3953
|
-
*
|
171
|
+
* Return the given PostgreSQL encoding ID as an rb_encoding.
|
3954
172
|
*
|
3955
|
-
*
|
3956
|
-
*
|
173
|
+
* - returns NULL if the client encoding is 'SQL_ASCII'.
|
174
|
+
* - returns ASCII-8BIT if the client encoding is unknown.
|
3957
175
|
*/
|
3958
|
-
|
3959
|
-
|
176
|
+
rb_encoding *
|
177
|
+
pg_get_pg_encoding_as_rb_encoding( int enc_id )
|
3960
178
|
{
|
3961
179
|
rb_encoding *enc;
|
3962
|
-
int enc_id = PQclientEncoding(conn);
|
3963
180
|
|
3964
|
-
if
|
181
|
+
/* Use the cached value if it exists */
|
182
|
+
if ( st_lookup(enc_pg2ruby, (st_data_t)enc_id, (st_data_t*)&enc) ) {
|
3965
183
|
return enc;
|
3966
184
|
}
|
3967
185
|
else {
|
3968
|
-
|
3969
|
-
const char *name = pg_encoding_to_char(enc_id);
|
3970
|
-
if (strcmp("SQL_ASCII", name) == 0) {
|
3971
|
-
enc = NULL;
|
3972
|
-
goto cache;
|
3973
|
-
}
|
3974
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
3975
|
-
if (strcmp(name, enc_pg2ruby_mapping[i][0]) == 0) {
|
3976
|
-
enc = rb_enc_find(enc_pg2ruby_mapping[i][1]);
|
3977
|
-
goto cache;
|
3978
|
-
}
|
3979
|
-
}
|
186
|
+
const char *name = pg_encoding_to_char( enc_id );
|
3980
187
|
|
3981
|
-
|
3982
|
-
|
3983
|
-
enc = find_or_create_johab();
|
3984
|
-
goto cache;
|
3985
|
-
}
|
188
|
+
enc = pg_get_pg_encname_as_rb_encoding( name );
|
189
|
+
st_insert( enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc );
|
3986
190
|
|
3987
|
-
enc
|
191
|
+
return enc;
|
3988
192
|
}
|
3989
|
-
cache:
|
3990
|
-
st_insert(enc_pg2ruby, (st_data_t)enc_id, (st_data_t)enc);
|
3991
|
-
return enc;
|
3992
|
-
}
|
3993
193
|
|
194
|
+
}
|
3994
195
|
|
3995
|
-
/*
|
3996
|
-
*
|
3997
|
-
*
|
196
|
+
/*
|
197
|
+
* Return the given PostgreSQL encoding name as an rb_encoding.
|
3998
198
|
*/
|
3999
|
-
|
4000
|
-
|
199
|
+
rb_encoding *
|
200
|
+
pg_get_pg_encname_as_rb_encoding( const char *pg_encname )
|
4001
201
|
{
|
4002
|
-
|
4003
|
-
const char *encname = NULL;
|
4004
|
-
int i;
|
202
|
+
size_t i;
|
4005
203
|
|
4006
|
-
|
4007
|
-
|
4008
|
-
|
4009
|
-
|
204
|
+
/* Trying looking it up in the conversion table */
|
205
|
+
for ( i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i ) {
|
206
|
+
if ( strcmp(pg_encname, pg_enc_pg2ruby_mapping[i][0]) == 0 )
|
207
|
+
return rb_enc_find( pg_enc_pg2ruby_mapping[i][1] );
|
4010
208
|
}
|
4011
209
|
|
4012
|
-
|
4013
|
-
|
4014
|
-
|
4015
|
-
}
|
210
|
+
/* JOHAB isn't a builtin encoding, so make up a dummy encoding if it's seen */
|
211
|
+
if ( strncmp(pg_encname, "JOHAB", 5) == 0 )
|
212
|
+
return pg_find_or_create_johab();
|
4016
213
|
|
4017
|
-
|
4018
|
-
|
4019
|
-
* call-seq:
|
4020
|
-
* conn.internal_encoding() -> Encoding
|
4021
|
-
*
|
4022
|
-
* defined in Ruby 1.9 or later.
|
4023
|
-
*
|
4024
|
-
* Returns:
|
4025
|
-
* * an Encoding - client_encoding of the connection as a Ruby Encoding object.
|
4026
|
-
* * nil - the client_encoding is 'SQL_ASCII'
|
4027
|
-
*/
|
4028
|
-
static VALUE
|
4029
|
-
pgconn_internal_encoding(VALUE self)
|
4030
|
-
{
|
4031
|
-
return rb_enc_from_encoding(pgconn_get_client_encoding_as_rb_encoding(get_pgconn(self)));
|
214
|
+
/* Fallthrough to ASCII-8BIT */
|
215
|
+
return rb_ascii8bit_encoding();
|
4032
216
|
}
|
4033
217
|
|
4034
|
-
static VALUE pgconn_external_encoding(VALUE self);
|
4035
|
-
|
4036
218
|
/*
|
4037
|
-
*
|
4038
|
-
* conn.internal_encoding = value
|
4039
|
-
*
|
4040
|
-
* A wrapper of +PGconn#set_client_encoding+.
|
4041
|
-
* defined in Ruby 1.9 or later.
|
4042
|
-
*
|
4043
|
-
* +value+ can be one of:
|
4044
|
-
* * an Encoding
|
4045
|
-
* * a String - a name of Encoding
|
4046
|
-
* * +nil+ - sets 'SQL_ASCII' to the client_encoding.
|
219
|
+
* Get the client encoding of the specified connection handle and return it as a rb_encoding.
|
4047
220
|
*/
|
4048
|
-
|
4049
|
-
|
221
|
+
rb_encoding *
|
222
|
+
pg_conn_enc_get( PGconn *conn )
|
4050
223
|
{
|
4051
|
-
|
4052
|
-
|
4053
|
-
return enc;
|
4054
|
-
}
|
4055
|
-
else if (TYPE(enc) == T_STRING && strcasecmp("JOHAB", RSTRING_PTR(enc)) == 0) {
|
4056
|
-
pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
4057
|
-
return enc;
|
4058
|
-
}
|
4059
|
-
else {
|
4060
|
-
int i;
|
4061
|
-
const char *name;
|
4062
|
-
name = rb_enc_name(rb_to_encoding(enc));
|
4063
|
-
|
4064
|
-
/* sequential search becuase rarely called */
|
4065
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
4066
|
-
if (strcmp(name, enc_pg2ruby_mapping[i][1]) == 0) {
|
4067
|
-
if (PQsetClientEncoding(get_pgconn(self), enc_pg2ruby_mapping[i][0]) == -1) {
|
4068
|
-
VALUE server_encoding = pgconn_external_encoding(self);
|
4069
|
-
rb_raise(rb_eEncCompatError, "imcompatible character encodings: %s and %s",
|
4070
|
-
rb_enc_name(rb_to_encoding(server_encoding)),
|
4071
|
-
enc_pg2ruby_mapping[i][0]);
|
4072
|
-
}
|
4073
|
-
return enc;
|
4074
|
-
}
|
4075
|
-
}
|
4076
|
-
|
4077
|
-
/* Ruby 1.9.1 does not support JOHAB */
|
4078
|
-
if (strcasecmp(name, "JOHAB") == 0) {
|
4079
|
-
pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
|
4080
|
-
return enc;
|
4081
|
-
}
|
4082
|
-
}
|
4083
|
-
|
4084
|
-
enc = rb_inspect(enc);
|
4085
|
-
rb_raise(rb_ePGError, "unknown encoding: %s", StringValuePtr(enc));
|
224
|
+
int enc_id = PQclientEncoding( conn );
|
225
|
+
return pg_get_pg_encoding_as_rb_encoding( enc_id );
|
4086
226
|
}
|
4087
227
|
|
4088
228
|
|
4089
|
-
|
4090
|
-
static VALUE enc_server_encoding_getvalue(VALUE pgresult)
|
4091
|
-
{
|
4092
|
-
return pgresult_getvalue(pgresult, INT2FIX(0), INT2FIX(0));
|
4093
|
-
}
|
4094
|
-
|
4095
229
|
/*
|
4096
|
-
*
|
4097
|
-
* conn.external_encoding() -> Encoding
|
4098
|
-
*
|
4099
|
-
* defined in Ruby 1.9 or later.
|
4100
|
-
* * Returns the server_encoding of the connected database as a Ruby Encoding object.
|
4101
|
-
* * Maps 'SQL_ASCII' to ASCII-8BIT.
|
230
|
+
* Returns the given rb_encoding as the equivalent PostgreSQL encoding string.
|
4102
231
|
*/
|
4103
|
-
|
4104
|
-
|
232
|
+
const char *
|
233
|
+
pg_get_rb_encoding_as_pg_encoding( rb_encoding *enc )
|
4105
234
|
{
|
4106
|
-
|
4107
|
-
|
4108
|
-
|
4109
|
-
return enc;
|
4110
|
-
}
|
4111
|
-
else {
|
4112
|
-
int i;
|
4113
|
-
VALUE query = rb_usascii_str_new_cstr("SHOW server_encoding");
|
4114
|
-
VALUE pgresult = pgconn_exec(1, &query, self);
|
4115
|
-
VALUE enc_name = rb_ensure(enc_server_encoding_getvalue, pgresult, pgresult_clear, pgresult);
|
4116
|
-
|
4117
|
-
if (strcmp("SQL_ASCII", StringValuePtr(enc_name)) == 0) {
|
4118
|
-
enc = rb_enc_from_encoding(rb_ascii8bit_encoding());
|
4119
|
-
goto cache;
|
4120
|
-
}
|
4121
|
-
for (i = 0; i < sizeof(enc_pg2ruby_mapping)/sizeof(enc_pg2ruby_mapping[0]); ++i) {
|
4122
|
-
if (strcmp(StringValuePtr(enc_name), enc_pg2ruby_mapping[i][0]) == 0) {
|
4123
|
-
enc = rb_enc_from_encoding(rb_enc_find(enc_pg2ruby_mapping[i][1]));
|
4124
|
-
goto cache;
|
4125
|
-
}
|
4126
|
-
}
|
235
|
+
const char *rb_encname = rb_enc_name( enc );
|
236
|
+
const char *encname = NULL;
|
237
|
+
size_t i;
|
4127
238
|
|
4128
|
-
|
4129
|
-
if (strcmp(
|
4130
|
-
|
4131
|
-
goto cache;
|
239
|
+
for (i = 0; i < sizeof(pg_enc_pg2ruby_mapping)/sizeof(pg_enc_pg2ruby_mapping[0]); ++i) {
|
240
|
+
if (strcmp(rb_encname, pg_enc_pg2ruby_mapping[i][1]) == 0) {
|
241
|
+
encname = pg_enc_pg2ruby_mapping[i][0];
|
4132
242
|
}
|
4133
|
-
|
4134
|
-
/* fallback */
|
4135
|
-
enc = rb_enc_from_encoding(rb_enc_find(StringValuePtr(enc_name)));
|
4136
243
|
}
|
4137
244
|
|
4138
|
-
|
4139
|
-
rb_iv_set(self, "@external_encoding", enc);
|
4140
|
-
return enc;
|
4141
|
-
}
|
245
|
+
if ( !encname ) encname = "SQL_ASCII";
|
4142
246
|
|
4143
|
-
|
4144
|
-
init_m17n(void)
|
4145
|
-
{
|
4146
|
-
enc_pg2ruby = st_init_numtable();
|
4147
|
-
s_id_index = rb_intern("@encoding");
|
4148
|
-
rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
|
4149
|
-
rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
|
4150
|
-
rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
|
247
|
+
return encname;
|
4151
248
|
}
|
4152
249
|
|
250
|
+
#endif /* M17N_SUPPORTED */
|
4153
251
|
|
4154
|
-
#endif
|
4155
|
-
/**************************************************************************/
|
4156
252
|
|
4157
253
|
void
|
4158
254
|
Init_pg_ext()
|
4159
255
|
{
|
4160
|
-
|
4161
|
-
|
4162
|
-
|
4163
|
-
|
4164
|
-
/* Library version */
|
4165
|
-
rb_define_const( rb_cPGconn, "VERSION", rb_str_new2(VERSION) );
|
4166
|
-
|
4167
|
-
/*************************
|
4168
|
-
* PGError
|
4169
|
-
*************************/
|
4170
|
-
rb_define_alias(rb_ePGError, "error", "message");
|
4171
|
-
rb_define_attr(rb_ePGError, "connection", 1, 0);
|
4172
|
-
rb_define_attr(rb_ePGError, "result", 1, 0);
|
256
|
+
rb_mPG = rb_define_module( "PG" );
|
257
|
+
rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
|
258
|
+
rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
|
4173
259
|
|
4174
260
|
/*************************
|
4175
|
-
*
|
261
|
+
* PG::Error
|
4176
262
|
*************************/
|
263
|
+
rb_define_alias( rb_ePGerror, "error", "message" );
|
264
|
+
rb_define_attr( rb_ePGerror, "connection", 1, 0 );
|
265
|
+
rb_define_attr( rb_ePGerror, "result", 1, 0 );
|
4177
266
|
|
4178
|
-
/******
|
4179
|
-
rb_define_alloc_func(rb_cPGconn, pgconn_alloc);
|
4180
|
-
rb_define_singleton_alias(rb_cPGconn, "connect", "new");
|
4181
|
-
rb_define_singleton_alias(rb_cPGconn, "open", "new");
|
4182
|
-
rb_define_singleton_alias(rb_cPGconn, "setdb", "new");
|
4183
|
-
rb_define_singleton_alias(rb_cPGconn, "setdblogin", "new");
|
4184
|
-
rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4185
|
-
rb_define_singleton_alias(rb_cPGconn, "escape", "escape_string");
|
4186
|
-
rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4187
|
-
rb_define_singleton_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4188
|
-
rb_define_singleton_method(rb_cPGconn, "isthreadsafe", pgconn_s_isthreadsafe, 0);
|
4189
|
-
rb_define_singleton_method(rb_cPGconn, "encrypt_password", pgconn_s_encrypt_password, 2);
|
4190
|
-
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4191
|
-
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4192
|
-
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4193
|
-
|
4194
|
-
/****** PGconn CLASS CONSTANTS: Connection Status ******/
|
267
|
+
/****** PG::Connection CLASS CONSTANTS: Connection Status ******/
|
4195
268
|
|
4196
269
|
/* Connection succeeded */
|
4197
|
-
rb_define_const(
|
270
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_OK", INT2FIX(CONNECTION_OK));
|
4198
271
|
/* Connection failed */
|
4199
|
-
rb_define_const(
|
272
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_BAD", INT2FIX(CONNECTION_BAD));
|
4200
273
|
|
4201
|
-
/******
|
274
|
+
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection status ******/
|
4202
275
|
|
4203
276
|
/* Waiting for connection to be made. */
|
4204
|
-
rb_define_const(
|
277
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_STARTED", INT2FIX(CONNECTION_STARTED));
|
4205
278
|
/* Connection OK; waiting to send. */
|
4206
|
-
rb_define_const(
|
279
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_MADE", INT2FIX(CONNECTION_MADE));
|
4207
280
|
/* Waiting for a response from the server. */
|
4208
|
-
rb_define_const(
|
281
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_AWAITING_RESPONSE", INT2FIX(CONNECTION_AWAITING_RESPONSE));
|
4209
282
|
/* Received authentication; waiting for backend start-up to finish. */
|
4210
|
-
rb_define_const(
|
283
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_AUTH_OK", INT2FIX(CONNECTION_AUTH_OK));
|
4211
284
|
/* Negotiating SSL encryption. */
|
4212
|
-
rb_define_const(
|
285
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SSL_STARTUP", INT2FIX(CONNECTION_SSL_STARTUP));
|
4213
286
|
/* Negotiating environment-driven parameter settings. */
|
4214
|
-
rb_define_const(
|
287
|
+
rb_define_const(rb_mPGconstants, "CONNECTION_SETENV", INT2FIX(CONNECTION_SETENV));
|
4215
288
|
|
4216
|
-
/******
|
289
|
+
/****** PG::Connection CLASS CONSTANTS: Nonblocking connection polling status ******/
|
4217
290
|
|
4218
291
|
/* Async connection is waiting to read */
|
4219
|
-
rb_define_const(
|
292
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_READING", INT2FIX(PGRES_POLLING_READING));
|
4220
293
|
/* Async connection is waiting to write */
|
4221
|
-
rb_define_const(
|
294
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_WRITING", INT2FIX(PGRES_POLLING_WRITING));
|
4222
295
|
/* Async connection failed or was reset */
|
4223
|
-
rb_define_const(
|
296
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_FAILED", INT2FIX(PGRES_POLLING_FAILED));
|
4224
297
|
/* Async connection succeeded */
|
4225
|
-
rb_define_const(
|
298
|
+
rb_define_const(rb_mPGconstants, "PGRES_POLLING_OK", INT2FIX(PGRES_POLLING_OK));
|
4226
299
|
|
4227
|
-
/******
|
300
|
+
/****** PG::Connection CLASS CONSTANTS: Transaction Status ******/
|
4228
301
|
|
4229
302
|
/* Transaction is currently idle (#transaction_status) */
|
4230
|
-
rb_define_const(
|
303
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_IDLE", INT2FIX(PQTRANS_IDLE));
|
4231
304
|
/* Transaction is currently active; query has been sent to the server, but not yet completed. (#transaction_status) */
|
4232
|
-
rb_define_const(
|
305
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_ACTIVE", INT2FIX(PQTRANS_ACTIVE));
|
4233
306
|
/* Transaction is currently idle, in a valid transaction block (#transaction_status) */
|
4234
|
-
rb_define_const(
|
307
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_INTRANS", INT2FIX(PQTRANS_INTRANS));
|
4235
308
|
/* Transaction is currently idle, in a failed transaction block (#transaction_status) */
|
4236
|
-
rb_define_const(
|
309
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_INERROR", INT2FIX(PQTRANS_INERROR));
|
4237
310
|
/* Transaction's connection is bad (#transaction_status) */
|
4238
|
-
rb_define_const(
|
311
|
+
rb_define_const(rb_mPGconstants, "PQTRANS_UNKNOWN", INT2FIX(PQTRANS_UNKNOWN));
|
4239
312
|
|
4240
|
-
/******
|
313
|
+
/****** PG::Connection CLASS CONSTANTS: Error Verbosity ******/
|
4241
314
|
|
4242
315
|
/* Terse error verbosity level (#set_error_verbosity) */
|
4243
|
-
rb_define_const(
|
316
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_TERSE", INT2FIX(PQERRORS_TERSE));
|
4244
317
|
/* Default error verbosity level (#set_error_verbosity) */
|
4245
|
-
rb_define_const(
|
318
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_DEFAULT", INT2FIX(PQERRORS_DEFAULT));
|
4246
319
|
/* Verbose error verbosity level (#set_error_verbosity) */
|
4247
|
-
rb_define_const(
|
320
|
+
rb_define_const(rb_mPGconstants, "PQERRORS_VERBOSE", INT2FIX(PQERRORS_VERBOSE));
|
4248
321
|
|
4249
|
-
/******
|
322
|
+
/****** PG::Connection CLASS CONSTANTS: Large Objects ******/
|
4250
323
|
|
4251
324
|
/* Flag for #lo_creat, #lo_open -- open for writing */
|
4252
|
-
rb_define_const(
|
325
|
+
rb_define_const(rb_mPGconstants, "INV_WRITE", INT2FIX(INV_WRITE));
|
4253
326
|
/* Flag for #lo_creat, #lo_open -- open for reading */
|
4254
|
-
rb_define_const(
|
327
|
+
rb_define_const(rb_mPGconstants, "INV_READ", INT2FIX(INV_READ));
|
4255
328
|
/* Flag for #lo_lseek -- seek from object start */
|
4256
|
-
rb_define_const(
|
329
|
+
rb_define_const(rb_mPGconstants, "SEEK_SET", INT2FIX(SEEK_SET));
|
4257
330
|
/* Flag for #lo_lseek -- seek from current position */
|
4258
|
-
rb_define_const(
|
331
|
+
rb_define_const(rb_mPGconstants, "SEEK_CUR", INT2FIX(SEEK_CUR));
|
4259
332
|
/* Flag for #lo_lseek -- seek from object end */
|
4260
|
-
rb_define_const(
|
4261
|
-
|
4262
|
-
/****** PGconn INSTANCE METHODS: Connection Control ******/
|
4263
|
-
rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
|
4264
|
-
rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
|
4265
|
-
rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
|
4266
|
-
rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
|
4267
|
-
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4268
|
-
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4269
|
-
rb_define_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4270
|
-
rb_define_alias(rb_cPGconn, "close", "finish");
|
4271
|
-
|
4272
|
-
/****** PGconn INSTANCE METHODS: Connection Status ******/
|
4273
|
-
rb_define_method(rb_cPGconn, "db", pgconn_db, 0);
|
4274
|
-
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
4275
|
-
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
4276
|
-
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
4277
|
-
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4278
|
-
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4279
|
-
rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
|
4280
|
-
rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
|
4281
|
-
rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
|
4282
|
-
rb_define_method(rb_cPGconn, "parameter_status", pgconn_parameter_status, 1);
|
4283
|
-
rb_define_method(rb_cPGconn, "protocol_version", pgconn_protocol_version, 0);
|
4284
|
-
rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
|
4285
|
-
rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
|
4286
|
-
rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
|
4287
|
-
rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
|
4288
|
-
rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
|
4289
|
-
rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
|
4290
|
-
//rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0);
|
4291
|
-
|
4292
|
-
/****** PGconn INSTANCE METHODS: Command Execution ******/
|
4293
|
-
rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
|
4294
|
-
rb_define_alias(rb_cPGconn, "query", "exec");
|
4295
|
-
rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
|
4296
|
-
rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
|
4297
|
-
rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
|
4298
|
-
rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
|
4299
|
-
rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
|
4300
|
-
rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
|
4301
|
-
rb_define_alias(rb_cPGconn, "escape", "escape_string");
|
4302
|
-
rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
|
4303
|
-
rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
|
4304
|
-
|
4305
|
-
/****** PGconn INSTANCE METHODS: Asynchronous Command Processing ******/
|
4306
|
-
rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
|
4307
|
-
rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
|
4308
|
-
rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
|
4309
|
-
rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
|
4310
|
-
rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
|
4311
|
-
rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
|
4312
|
-
rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
|
4313
|
-
rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
|
4314
|
-
rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
|
4315
|
-
rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
|
4316
|
-
rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
|
4317
|
-
rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
|
4318
|
-
|
4319
|
-
/****** PGconn INSTANCE METHODS: Cancelling Queries in Progress ******/
|
4320
|
-
rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
|
4321
|
-
|
4322
|
-
/****** PGconn INSTANCE METHODS: NOTIFY ******/
|
4323
|
-
rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
|
4324
|
-
|
4325
|
-
/****** PGconn INSTANCE METHODS: COPY ******/
|
4326
|
-
rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, 1);
|
4327
|
-
rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
|
4328
|
-
rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
|
333
|
+
rb_define_const(rb_mPGconstants, "SEEK_END", INT2FIX(SEEK_END));
|
4329
334
|
|
4330
|
-
/****** PGconn INSTANCE METHODS: Control Functions ******/
|
4331
|
-
rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
|
4332
|
-
rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
|
4333
|
-
rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
|
4334
335
|
|
4335
|
-
/******
|
4336
|
-
rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
|
4337
|
-
rb_define_method(rb_cPGconn, "set_notice_processor", pgconn_set_notice_processor, 0);
|
4338
|
-
|
4339
|
-
/****** PGconn INSTANCE METHODS: Other ******/
|
4340
|
-
rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
|
4341
|
-
rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
|
4342
|
-
rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
|
4343
|
-
rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
|
4344
|
-
rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
|
4345
|
-
rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
|
4346
|
-
rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4347
|
-
rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
|
4348
|
-
rb_define_alias(rb_cPGconn, "async_query", "async_exec");
|
4349
|
-
rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
|
4350
|
-
|
4351
|
-
/****** PGconn INSTANCE METHODS: Large Object Support ******/
|
4352
|
-
rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
|
4353
|
-
rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
|
4354
|
-
rb_define_method(rb_cPGconn, "lo_create", pgconn_locreate, 1);
|
4355
|
-
rb_define_alias(rb_cPGconn, "locreate", "lo_create");
|
4356
|
-
rb_define_method(rb_cPGconn, "lo_import", pgconn_loimport, 1);
|
4357
|
-
rb_define_alias(rb_cPGconn, "loimport", "lo_import");
|
4358
|
-
rb_define_method(rb_cPGconn, "lo_export", pgconn_loexport, 2);
|
4359
|
-
rb_define_alias(rb_cPGconn, "loexport", "lo_export");
|
4360
|
-
rb_define_method(rb_cPGconn, "lo_open", pgconn_loopen, -1);
|
4361
|
-
rb_define_alias(rb_cPGconn, "loopen", "lo_open");
|
4362
|
-
rb_define_method(rb_cPGconn, "lo_write",pgconn_lowrite, 2);
|
4363
|
-
rb_define_alias(rb_cPGconn, "lowrite", "lo_write");
|
4364
|
-
rb_define_method(rb_cPGconn, "lo_read",pgconn_loread, 2);
|
4365
|
-
rb_define_alias(rb_cPGconn, "loread", "lo_read");
|
4366
|
-
rb_define_method(rb_cPGconn, "lo_lseek",pgconn_lolseek, 3);
|
4367
|
-
rb_define_alias(rb_cPGconn, "lolseek", "lo_lseek");
|
4368
|
-
rb_define_alias(rb_cPGconn, "lo_seek", "lo_lseek");
|
4369
|
-
rb_define_alias(rb_cPGconn, "loseek", "lo_lseek");
|
4370
|
-
rb_define_method(rb_cPGconn, "lo_tell",pgconn_lotell, 1);
|
4371
|
-
rb_define_alias(rb_cPGconn, "lotell", "lo_tell");
|
4372
|
-
rb_define_method(rb_cPGconn, "lo_truncate", pgconn_lotruncate, 2);
|
4373
|
-
rb_define_alias(rb_cPGconn, "lotruncate", "lo_truncate");
|
4374
|
-
rb_define_method(rb_cPGconn, "lo_close",pgconn_loclose, 1);
|
4375
|
-
rb_define_alias(rb_cPGconn, "loclose", "lo_close");
|
4376
|
-
rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
|
4377
|
-
rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
|
4378
|
-
|
4379
|
-
/*************************
|
4380
|
-
* PGresult
|
4381
|
-
*************************/
|
4382
|
-
rb_include_module(rb_cPGresult, rb_mEnumerable);
|
4383
|
-
|
4384
|
-
/****** PGresult CONSTANTS: result status ******/
|
336
|
+
/****** PG::Result CONSTANTS: result status ******/
|
4385
337
|
|
4386
338
|
/* #result_status constant: The string sent to the server was empty. */
|
4387
|
-
rb_define_const(
|
339
|
+
rb_define_const(rb_mPGconstants, "PGRES_EMPTY_QUERY", INT2FIX(PGRES_EMPTY_QUERY));
|
4388
340
|
/* #result_status constant: Successful completion of a command returning no data. */
|
4389
|
-
rb_define_const(
|
4390
|
-
|
341
|
+
rb_define_const(rb_mPGconstants, "PGRES_COMMAND_OK", INT2FIX(PGRES_COMMAND_OK));
|
342
|
+
/* #result_status constant: Successful completion of a command returning data
|
4391
343
|
(such as a SELECT or SHOW). */
|
4392
|
-
rb_define_const(
|
344
|
+
rb_define_const(rb_mPGconstants, "PGRES_TUPLES_OK", INT2FIX(PGRES_TUPLES_OK));
|
4393
345
|
/* #result_status constant: Copy Out (from server) data transfer started. */
|
4394
|
-
rb_define_const(
|
346
|
+
rb_define_const(rb_mPGconstants, "PGRES_COPY_OUT", INT2FIX(PGRES_COPY_OUT));
|
4395
347
|
/* #result_status constant: Copy In (to server) data transfer started. */
|
4396
|
-
rb_define_const(
|
348
|
+
rb_define_const(rb_mPGconstants, "PGRES_COPY_IN", INT2FIX(PGRES_COPY_IN));
|
4397
349
|
/* #result_status constant: The server’s response was not understood. */
|
4398
|
-
rb_define_const(
|
350
|
+
rb_define_const(rb_mPGconstants, "PGRES_BAD_RESPONSE", INT2FIX(PGRES_BAD_RESPONSE));
|
4399
351
|
/* #result_status constant: A nonfatal error (a notice or warning) occurred. */
|
4400
|
-
rb_define_const(
|
352
|
+
rb_define_const(rb_mPGconstants, "PGRES_NONFATAL_ERROR",INT2FIX(PGRES_NONFATAL_ERROR));
|
4401
353
|
/* #result_status constant: A fatal error occurred. */
|
4402
|
-
rb_define_const(
|
354
|
+
rb_define_const(rb_mPGconstants, "PGRES_FATAL_ERROR", INT2FIX(PGRES_FATAL_ERROR));
|
4403
355
|
|
4404
|
-
/******
|
356
|
+
/****** Result CONSTANTS: result error field codes ******/
|
4405
357
|
|
4406
358
|
/* #result_error_field argument constant: The severity; the field contents
|
4407
359
|
* are ERROR, FATAL, or PANIC (in an error message), or WARNING, NOTICE,
|
4408
360
|
* DEBUG, INFO, or LOG (in a notice message), or a localized translation
|
4409
361
|
* of one of these. Always present.
|
4410
362
|
*/
|
4411
|
-
rb_define_const(
|
363
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SEVERITY", INT2FIX(PG_DIAG_SEVERITY));
|
364
|
+
|
4412
365
|
/* #result_error_field argument constant: The SQLSTATE code for the
|
4413
366
|
* error. The SQLSTATE code identies the type of error that has occurred;
|
4414
367
|
* it can be used by front-end applications to perform specic operations
|
@@ -4416,97 +369,79 @@ Init_pg_ext()
|
|
4416
369
|
* error. For a list of the possible SQLSTATE codes, see Appendix A.
|
4417
370
|
* This eld is not localizable, and is always present.
|
4418
371
|
*/
|
4419
|
-
rb_define_const(
|
372
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SQLSTATE", INT2FIX(PG_DIAG_SQLSTATE));
|
373
|
+
|
4420
374
|
/* #result_error_field argument constant: The primary human-readable
|
4421
375
|
* error message (typically one line). Always present. */
|
4422
|
-
rb_define_const(
|
376
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_PRIMARY", INT2FIX(PG_DIAG_MESSAGE_PRIMARY));
|
377
|
+
|
4423
378
|
/* #result_error_field argument constant: Detail: an optional secondary
|
4424
379
|
* error message carrying more detail about the problem. Might run to
|
4425
380
|
* multiple lines.
|
4426
381
|
*/
|
4427
|
-
rb_define_const(
|
382
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_DETAIL", INT2FIX(PG_DIAG_MESSAGE_DETAIL));
|
383
|
+
|
4428
384
|
/* #result_error_field argument constant: Hint: an optional suggestion
|
4429
385
|
* what to do about the problem. This is intended to differ from detail
|
4430
386
|
* in that it offers advice (potentially inappropriate) rather than
|
4431
387
|
* hard facts. Might run to multiple lines.
|
4432
388
|
*/
|
4433
|
-
|
389
|
+
|
390
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_MESSAGE_HINT", INT2FIX(PG_DIAG_MESSAGE_HINT));
|
4434
391
|
/* #result_error_field argument constant: A string containing a decimal
|
4435
392
|
* integer indicating an error cursor position as an index into the
|
4436
393
|
* original statement string. The rst character has index 1, and
|
4437
394
|
* positions are measured in characters not bytes.
|
4438
395
|
*/
|
4439
|
-
|
396
|
+
|
397
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_STATEMENT_POSITION", INT2FIX(PG_DIAG_STATEMENT_POSITION));
|
4440
398
|
/* #result_error_field argument constant: This is dened the same as
|
4441
399
|
* the PG_DIAG_STATEMENT_POSITION eld, but it is used when the cursor
|
4442
400
|
* position refers to an internally generated command rather than the
|
4443
401
|
* one submitted by the client. The PG_DIAG_INTERNAL_QUERY eld will
|
4444
402
|
* always appear when this eld appears.
|
4445
403
|
*/
|
4446
|
-
|
404
|
+
|
405
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_POSITION", INT2FIX(PG_DIAG_INTERNAL_POSITION));
|
4447
406
|
/* #result_error_field argument constant: The text of a failed
|
4448
407
|
* internally-generated command. This could be, for example, a SQL
|
4449
408
|
* query issued by a PL/pgSQL function.
|
4450
409
|
*/
|
4451
|
-
|
410
|
+
|
411
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_INTERNAL_QUERY", INT2FIX(PG_DIAG_INTERNAL_QUERY));
|
4452
412
|
/* #result_error_field argument constant: An indication of the context
|
4453
413
|
* in which the error occurred. Presently this includes a call stack
|
4454
414
|
* traceback of active procedural language functions and internally-generated
|
4455
415
|
* queries. The trace is one entry per line, most recent rst.
|
4456
416
|
*/
|
4457
|
-
|
417
|
+
|
418
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_CONTEXT", INT2FIX(PG_DIAG_CONTEXT));
|
4458
419
|
/* #result_error_field argument constant: The le name of the source-code
|
4459
420
|
* location where the error was reported. */
|
4460
|
-
rb_define_const(
|
421
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FILE", INT2FIX(PG_DIAG_SOURCE_FILE));
|
422
|
+
|
4461
423
|
/* #result_error_field argument constant: The line number of the
|
4462
424
|
* source-code location where the error was reported. */
|
4463
|
-
rb_define_const(
|
425
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_LINE", INT2FIX(PG_DIAG_SOURCE_LINE));
|
426
|
+
|
4464
427
|
/* #result_error_field argument constant: The name of the source-code
|
4465
428
|
* function reporting the error. */
|
4466
|
-
rb_define_const(
|
429
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FUNCTION", INT2FIX(PG_DIAG_SOURCE_FUNCTION));
|
4467
430
|
|
4468
431
|
/* Invalid OID constant */
|
4469
|
-
rb_define_const(
|
4470
|
-
|
4471
|
-
/****** PGresult INSTANCE METHODS: libpq ******/
|
4472
|
-
rb_define_method(rb_cPGresult, "result_status", pgresult_result_status, 0);
|
4473
|
-
rb_define_method(rb_cPGresult, "res_status", pgresult_res_status, 1);
|
4474
|
-
rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
|
4475
|
-
rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
|
4476
|
-
rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
|
4477
|
-
rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
|
4478
|
-
rb_define_method(rb_cPGresult, "clear", pgresult_clear, 0);
|
4479
|
-
rb_define_method(rb_cPGresult, "ntuples", pgresult_ntuples, 0);
|
4480
|
-
rb_define_alias(rb_cPGresult, "num_tuples", "ntuples");
|
4481
|
-
rb_define_method(rb_cPGresult, "nfields", pgresult_nfields, 0);
|
4482
|
-
rb_define_alias(rb_cPGresult, "num_fields", "nfields");
|
4483
|
-
rb_define_method(rb_cPGresult, "fname", pgresult_fname, 1);
|
4484
|
-
rb_define_method(rb_cPGresult, "fnumber", pgresult_fnumber, 1);
|
4485
|
-
rb_define_method(rb_cPGresult, "ftable", pgresult_ftable, 1);
|
4486
|
-
rb_define_method(rb_cPGresult, "ftablecol", pgresult_ftablecol, 1);
|
4487
|
-
rb_define_method(rb_cPGresult, "fformat", pgresult_fformat, 1);
|
4488
|
-
rb_define_method(rb_cPGresult, "ftype", pgresult_ftype, 1);
|
4489
|
-
rb_define_method(rb_cPGresult, "fmod", pgresult_fmod, 1);
|
4490
|
-
rb_define_method(rb_cPGresult, "fsize", pgresult_fsize, 1);
|
4491
|
-
rb_define_method(rb_cPGresult, "getvalue", pgresult_getvalue, 2);
|
4492
|
-
rb_define_method(rb_cPGresult, "getisnull", pgresult_getisnull, 2);
|
4493
|
-
rb_define_method(rb_cPGresult, "getlength", pgresult_getlength, 2);
|
4494
|
-
rb_define_method(rb_cPGresult, "nparams", pgresult_nparams, 0);
|
4495
|
-
rb_define_method(rb_cPGresult, "paramtype", pgresult_paramtype, 1);
|
4496
|
-
rb_define_method(rb_cPGresult, "cmd_status", pgresult_cmd_status, 0);
|
4497
|
-
rb_define_method(rb_cPGresult, "cmd_tuples", pgresult_cmd_tuples, 0);
|
4498
|
-
rb_define_alias(rb_cPGresult, "cmdtuples", "cmd_tuples");
|
4499
|
-
rb_define_method(rb_cPGresult, "oid_value", pgresult_oid_value, 0);
|
432
|
+
rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
|
433
|
+
rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
|
4500
434
|
|
4501
|
-
|
4502
|
-
|
4503
|
-
rb_define_method(rb_cPGresult, "each", pgresult_each, 0);
|
4504
|
-
rb_define_method(rb_cPGresult, "fields", pgresult_fields, 0);
|
4505
|
-
rb_define_method(rb_cPGresult, "values", pgresult_values, 0);
|
4506
|
-
rb_define_method(rb_cPGresult, "column_values", pgresult_column_values, 1);
|
4507
|
-
rb_define_method(rb_cPGresult, "field_values", pgresult_field_values, 1);
|
435
|
+
/* Add the constants to the toplevel namespace */
|
436
|
+
rb_include_module( rb_mPG, rb_mPGconstants );
|
4508
437
|
|
4509
|
-
#ifdef M17N_SUPPORTED
|
4510
|
-
|
438
|
+
#ifdef M17N_SUPPORTED
|
439
|
+
enc_pg2ruby = st_init_numtable();
|
440
|
+
s_id_index = rb_intern("@encoding");
|
4511
441
|
#endif
|
442
|
+
|
443
|
+
/* Initialize the main extension classes */
|
444
|
+
init_pg_connection();
|
445
|
+
init_pg_result();
|
4512
446
|
}
|
447
|
+
|