pgsql 1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/LICENSE ADDED
@@ -0,0 +1,35 @@
1
+ _
2
+ _ __ __ _ ___ __ _| |
3
+ | '_ \ / _` / __|/ _` | |
4
+ | |_) | (_| \__ \ (_| | |
5
+ | .__/ \__, |___/\__, |_|
6
+ |_| |___/ |_|
7
+
8
+
9
+ Copyright (c) 2011-2013, Bertram Scharpf <software@bertram-scharpf.de>.
10
+ All rights reserved.
11
+
12
+ Redistribution and use in source and binary forms, with or without
13
+ modification, are permitted provided that the following conditions are
14
+ met:
15
+
16
+ * Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+
19
+ * Redistributions in binary form must reproduce the above copyright
20
+ notice, this list of conditions and the following disclaimer in
21
+ the documentation and/or other materials provided with the
22
+ distribution.
23
+
24
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
25
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
28
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
32
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
33
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
34
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+
data/README ADDED
@@ -0,0 +1,47 @@
1
+ _
2
+ _ __ __ _ ___ __ _| |
3
+ | '_ \ / _` / __|/ _` | |
4
+ | |_) | (_| \__ \ (_| | |
5
+ | .__/ \__, |___/\__, |_|
6
+ |_| |___/ |_|
7
+
8
+ == Description
9
+
10
+ A PostgreSQL library that was carefully designed.
11
+
12
+ == Features
13
+
14
+ * Connection parameters from hash
15
+ * Query parameters
16
+ * Asynchronous queries
17
+ * Quick query of single lines or values
18
+ * Full PostgreSQL quoting support
19
+ * Built-in transactions and savepoints by Ruby blocks
20
+
21
+ == Example
22
+
23
+ Write something like this:
24
+
25
+ require "pgsql"
26
+
27
+ Pg::Conn.open :dbname => "test1", :user => "jdoe" do |conn|
28
+ conn.exec "select * from mytable;" do |result|
29
+ result.each { |row|
30
+ l = row.join ", "
31
+ ...
32
+ }
33
+ end
34
+ cmd = <<-ENDSQL
35
+ select * from mytable where num=$1::integer;
36
+ ENDSQL
37
+ conn.query cmd, 42 do |row|
38
+ l = row.join ", "
39
+ ...
40
+ end
41
+ ...
42
+ end
43
+
44
+ == Thanks
45
+
46
+ In the remembrance of Guy Decoux.
47
+
data/lib/Rakefile ADDED
@@ -0,0 +1,31 @@
1
+ #
2
+ # Rakefile -- build the libraries
3
+ #
4
+
5
+ require "autorake"
6
+
7
+ c = compiler "-O2", "-fPIC"
8
+ l = linker "-shared"
9
+
10
+ rule ".o" => ".c" do |t|
11
+ c.cc t.name, t.source
12
+ end
13
+
14
+
15
+ DLs = {
16
+ "pgsql.so" => %w(module.o conn.o conn_quote.o conn_exec.o result.o ),
17
+ }
18
+
19
+ DLs.each { |k,v|
20
+ task k => v do |t|
21
+ l.cc t.name, t.prerequisites
22
+ end
23
+ }
24
+
25
+ task :default => DLs.keys
26
+
27
+ task :clean do
28
+ FileList[ "*.o", "*.so"].each { |f| rm_f f }
29
+ FileList[ "*.core"].each { |f| rm_f f }
30
+ end
31
+
data/lib/conn.c ADDED
@@ -0,0 +1,902 @@
1
+ /*
2
+ * conn.c -- PostgreSQL connection
3
+ */
4
+
5
+
6
+ #include "conn.h"
7
+
8
+
9
+ #if defined( HAVE_HEADER_ST_H)
10
+ #include <st.h>
11
+ #endif
12
+
13
+
14
+ extern void pg_check_conninvalid( struct pgconn_data *c);
15
+ static VALUE pgconnfailederror_new( struct pgconn_data *c, VALUE params);
16
+
17
+ static void pgconn_mark( struct pgconn_data *ptr);
18
+ static void pgconn_free( struct pgconn_data *ptr);
19
+ extern struct pgconn_data *get_pgconn( VALUE obj);
20
+ static VALUE pgconn_encode_in4out( struct pgconn_data *ptr, VALUE str);
21
+ extern const char *pgconn_destring( struct pgconn_data *ptr, VALUE str, int *len);
22
+ static VALUE pgconn_encode_out4in( struct pgconn_data *ptr, VALUE str);
23
+ extern VALUE pgconn_mkstring( struct pgconn_data *ptr, const char *str);
24
+ extern VALUE pgconn_mkstringn( struct pgconn_data *ptr, const char *str, int len);
25
+ static VALUE pgconn_alloc( VALUE cls);
26
+ static VALUE pgconn_s_connect( int argc, VALUE *argv, VALUE cls);
27
+ static VALUE pgconn_s_parse( VALUE cls, VALUE str);
28
+ static VALUE pgconn_init( int argc, VALUE *argv, VALUE self);
29
+ static int set_connect_params( st_data_t key, st_data_t val, st_data_t args);
30
+ static void connstr_to_hash( VALUE params, VALUE str);
31
+ static void connstr_passwd( VALUE self, VALUE params);
32
+ static VALUE connstr_getparam( VALUE yielded, VALUE params);
33
+
34
+ static VALUE pgconn_close( VALUE self);
35
+ static VALUE pgconn_reset( VALUE self);
36
+
37
+ static VALUE pgconn_client_encoding( VALUE self);
38
+ static VALUE pgconn_set_client_encoding( VALUE self, VALUE str);
39
+ #ifdef RUBY_ENCODING
40
+ static VALUE pgconn_externalenc( VALUE self);
41
+ static VALUE pgconn_set_externalenc( VALUE self, VALUE enc);
42
+ static VALUE pgconn_internalenc( VALUE self);
43
+ static VALUE pgconn_set_internalenc( VALUE self, VALUE enc);
44
+ #endif
45
+
46
+ static VALUE pgconn_protocol_version( VALUE self);
47
+ static VALUE pgconn_server_version( VALUE self);
48
+
49
+ static VALUE pgconn_dbname( VALUE self);
50
+ static VALUE pgconn_host( VALUE self);
51
+ static VALUE pgconn_options( VALUE self);
52
+ static VALUE pgconn_port( VALUE self);
53
+ static VALUE pgconn_tty( VALUE self);
54
+ static VALUE pgconn_user( VALUE self);
55
+ static VALUE pgconn_status( VALUE self);
56
+ static VALUE pgconn_error( VALUE self);
57
+
58
+ static VALUE pgconn_socket( VALUE self);
59
+
60
+ static VALUE pgconn_trace( int argc, VALUE *argv, VALUE self);
61
+ static VALUE pgconn_untrace( VALUE self);
62
+
63
+ static VALUE pgconn_on_notice( VALUE self);
64
+ static void notice_receiver( void *self, const PGresult *result);
65
+
66
+
67
+ VALUE rb_cPgConn;
68
+
69
+ static VALUE rb_ePgConnFailed;
70
+ static VALUE rb_ePgConnInvalid;
71
+
72
+
73
+
74
+ void
75
+ pg_check_conninvalid( struct pgconn_data *c)
76
+ {
77
+ if (c->conn == NULL)
78
+ rb_raise( rb_ePgConnInvalid, "Invalid connection (probably closed).");
79
+ }
80
+
81
+
82
+ VALUE
83
+ pgconnfailederror_new( struct pgconn_data *c, VALUE params)
84
+ {
85
+ VALUE msg, cfe;
86
+
87
+ msg = pgconn_mkstring( c, PQerrorMessage( c->conn));
88
+ cfe = rb_class_new_instance( 1, &msg, rb_ePgConnFailed);
89
+ rb_ivar_set( cfe, rb_intern( "@parameters"), params);
90
+ return cfe;
91
+ }
92
+
93
+
94
+
95
+ void
96
+ pgconn_mark( struct pgconn_data *ptr)
97
+ {
98
+ rb_gc_mark( ptr->notice);
99
+ #ifdef RUBY_ENCODING
100
+ rb_gc_mark( ptr->external);
101
+ rb_gc_mark( ptr->internal);
102
+ #endif
103
+ }
104
+
105
+ void
106
+ pgconn_free( struct pgconn_data *ptr)
107
+ {
108
+ if (ptr->conn != NULL)
109
+ PQfinish( ptr->conn);
110
+ free( ptr);
111
+ }
112
+
113
+ struct pgconn_data *
114
+ get_pgconn( VALUE obj)
115
+ {
116
+ struct pgconn_data *c;
117
+
118
+ Data_Get_Struct( obj, struct pgconn_data, c);
119
+ pg_check_conninvalid( c);
120
+ return c;
121
+ }
122
+
123
+
124
+ VALUE pgconn_encode_in4out( struct pgconn_data *ptr, VALUE str)
125
+ {
126
+ str = rb_obj_as_string( str);
127
+ #ifdef RUBY_ENCODING
128
+ if (rb_enc_compatible( str, ptr->external) == NULL)
129
+ str = rb_str_conv_enc( str, rb_enc_get( str), rb_to_encoding( ptr->external));
130
+ #endif
131
+ return str;
132
+ }
133
+
134
+ const char *pgconn_destring( struct pgconn_data *ptr, VALUE str, int *len)
135
+ {
136
+ VALUE s;
137
+
138
+ s = pgconn_encode_in4out( ptr, str);
139
+ if (len != NULL)
140
+ *len = RSTRING_LEN( s);
141
+ return RSTRING_PTR( s);
142
+ }
143
+
144
+
145
+ VALUE
146
+ pgconn_encode_out4in( struct pgconn_data *ptr, VALUE str)
147
+ {
148
+ #ifdef RUBY_ENCODING
149
+ rb_enc_associate( str, rb_to_encoding( ptr->external));
150
+ if (!NIL_P( ptr->internal))
151
+ str = rb_str_conv_enc( str, rb_enc_get( str), rb_to_encoding( ptr->internal));
152
+ #endif
153
+ return str;
154
+ }
155
+
156
+
157
+ VALUE
158
+ pgconn_mkstring( struct pgconn_data *ptr, const char *str)
159
+ {
160
+ VALUE r;
161
+
162
+ if (str) {
163
+ r = rb_tainted_str_new2( str);
164
+ pgconn_encode_out4in( ptr, r);
165
+ } else
166
+ r = Qnil;
167
+ return r;
168
+ }
169
+
170
+ VALUE
171
+ pgconn_mkstringn( struct pgconn_data *ptr, const char *str, int len)
172
+ {
173
+ VALUE r;
174
+
175
+ if (str) {
176
+ r = rb_tainted_str_new( str, len);
177
+ pgconn_encode_out4in( ptr, r);
178
+ } else
179
+ r = Qnil;
180
+ return r;
181
+ }
182
+
183
+ VALUE
184
+ pgconn_alloc( VALUE cls)
185
+ {
186
+ struct pgconn_data *c;
187
+ VALUE r;
188
+
189
+ r = Data_Make_Struct( cls, struct pgconn_data,
190
+ &pgconn_mark, &pgconn_free, c);
191
+ c->conn = NULL;
192
+ #ifdef RUBY_ENCODING
193
+ c->external = rb_enc_from_encoding( rb_default_external_encoding());
194
+ c->internal = rb_enc_from_encoding( rb_default_internal_encoding());
195
+ #endif
196
+ c->notice = Qnil;
197
+ return r;
198
+ }
199
+
200
+ /*
201
+ * Document-method: connect
202
+ *
203
+ * call-seq:
204
+ * Pg::Conn.connect( hash) -> conn
205
+ * Pg::Conn.connect( str, hash) -> conn
206
+ * Pg::Conn.connect( hash) { |conn| ... } -> obj
207
+ * Pg::Conn.connect( str, hash) { |conn| ... } -> obj
208
+ *
209
+ * Without a block this is the same as +Pg::Conn.new+. If a block is given,
210
+ * the connection will be closed afterwards.
211
+ */
212
+ VALUE
213
+ pgconn_s_connect( int argc, VALUE *argv, VALUE cls)
214
+ {
215
+ VALUE pgconn;
216
+
217
+ pgconn = rb_class_new_instance( argc, argv, cls);
218
+ return rb_block_given_p() ?
219
+ rb_ensure( rb_yield, pgconn, pgconn_close, pgconn) : pgconn;
220
+ }
221
+
222
+ /*
223
+ * call-seq:
224
+ * Pg::Conn.parse( str) -> hash
225
+ *
226
+ * Parse a connection string and return a hash with keys <code>:dbname</code>,
227
+ * <code>:user</code>, <code>:host</code>, etc.
228
+ *
229
+ */
230
+ VALUE
231
+ pgconn_s_parse( VALUE cls, VALUE str)
232
+ {
233
+ VALUE params;
234
+
235
+ params = rb_hash_new();
236
+ connstr_to_hash( params, str);
237
+ return params;
238
+ }
239
+
240
+
241
+ /*
242
+ * Document-method: new
243
+ *
244
+ * call-seq:
245
+ * Pg::Conn.new( hash) -> conn
246
+ * Pg::Conn.new( str, hash) -> conn
247
+ *
248
+ * Establish a connection to a PostgreSQL server.
249
+ * The parameters may be specified as a hash:
250
+ *
251
+ * c = Pg::Conn.new :dbname => "movies", :host => "jupiter", ...
252
+ *
253
+ * The most common parameters may be given in a URL-like
254
+ * connection string:
255
+ *
256
+ * "user:password@host:port/dbname"
257
+ *
258
+ * Any of these parts may be omitted. If there is no slash, the part after the
259
+ * @ sign will be read as database name.
260
+ *
261
+ * If the password is the empty string, and there is either an instance method
262
+ * or a class method <code>password?</code>, that method will be asked. This
263
+ * method may ask <code>yield :user</code> or <code>yield :dbname</code> and so
264
+ * on to get the connection parameters.
265
+ *
266
+ * See the PostgreSQL documentation for a full list:
267
+ * [http://www.postgresql.org/docs/current/interactive/libpq-connect.html#LIBPQ-PQCONNECTDBPARAMS]
268
+ *
269
+ * On failure, a +Pg::Error+ exception will be raised.
270
+ */
271
+ VALUE
272
+ pgconn_init( int argc, VALUE *argv, VALUE self)
273
+ {
274
+ VALUE str, params;
275
+ int l;
276
+ const char **keywords, **values;
277
+ const char **ptrs[ 3];
278
+ struct pgconn_data *c;
279
+
280
+ if (rb_scan_args( argc, argv, "02", &str, &params) < 2)
281
+ if (TYPE( str) != T_STRING) {
282
+ params = str;
283
+ str = Qnil;
284
+ }
285
+ if (NIL_P( params))
286
+ params = rb_hash_new();
287
+ else if (TYPE( params) != T_HASH)
288
+ params = rb_convert_type( params, T_HASH, "Hash", "to_hash");
289
+ else
290
+ params = rb_obj_dup( params);
291
+ if (!NIL_P( str))
292
+ connstr_to_hash( params, str);
293
+ connstr_passwd( self, params);
294
+
295
+ Data_Get_Struct( self, struct pgconn_data, c);
296
+
297
+ l = RHASH_SIZE( params) + 1;
298
+ keywords = (const char **) ALLOCA_N( char *, l);
299
+ values = (const char **) ALLOCA_N( char *, l);
300
+ ptrs[ 0] = keywords;
301
+ ptrs[ 1] = values;
302
+ ptrs[ 2] = (const char **) c;
303
+ st_foreach( RHASH_TBL( params), &set_connect_params, (st_data_t) ptrs);
304
+ *(ptrs[ 0]) = *(ptrs[ 1]) = NULL;
305
+
306
+ c->conn = PQconnectdbParams( keywords, values, 1);
307
+ if (PQstatus( c->conn) == CONNECTION_BAD)
308
+ rb_exc_raise( pgconnfailederror_new( c, params));
309
+
310
+ return self;
311
+ }
312
+
313
+ int
314
+ set_connect_params( st_data_t key, st_data_t val, st_data_t args)
315
+ {
316
+ const char ***ptrs = (const char ***)args;
317
+ struct pgconn_data *c;
318
+ VALUE k, v;
319
+
320
+ k = (VALUE) key;
321
+ v = (VALUE) val;
322
+ c = (struct pgconn_data *) ptrs[ 2];
323
+ if (!NIL_P( v)) {
324
+ *(ptrs[ 0]) = pgconn_destring( c, rb_obj_as_string( k), NULL);
325
+ *(ptrs[ 1]) = pgconn_destring( c, rb_obj_as_string( v), NULL);
326
+ ptrs[ 0]++;
327
+ ptrs[ 1]++;
328
+ }
329
+ return ST_CONTINUE;
330
+ }
331
+
332
+ static const char re_connstr[] =
333
+ "\\A"
334
+ "(?:(.*?)(?::(.*))?@)?" /* user:passwd@ */
335
+ "(?:(.*?)(?::(\\d+))?/)?(?:(.+))?" /* host:port/dbname */
336
+ "\\z"
337
+ ;
338
+
339
+ #define KEY_USER "user"
340
+ #define KEY_PASSWORD "password"
341
+ #define KEY_HOST "host"
342
+ #define KEY_PORT "port"
343
+ #define KEY_DBNAME "dbname"
344
+
345
+ void
346
+ connstr_to_hash( VALUE params, VALUE str)
347
+ {
348
+ VALUE re, match, m;
349
+
350
+ re = rb_reg_new( re_connstr, sizeof re_connstr - 1, 0);
351
+ if (RTEST( rb_reg_match( re, str))) {
352
+ match = rb_backref_get();
353
+ #define ADD_TO_RES( key, n) \
354
+ m = rb_reg_nth_match( n, match); \
355
+ if (!NIL_P( m)) rb_hash_aset( params, ID2SYM( rb_intern( key)), m)
356
+ ADD_TO_RES( KEY_USER, 1);
357
+ ADD_TO_RES( KEY_PASSWORD, 2);
358
+ ADD_TO_RES( KEY_HOST, 3);
359
+ ADD_TO_RES( KEY_PORT, 4);
360
+ ADD_TO_RES( KEY_DBNAME, 5);
361
+ #undef ADD_TO_RES
362
+ } else
363
+ rb_raise( rb_eArgError, "Invalid connection: %s", RSTRING_PTR( str));
364
+ }
365
+
366
+ void
367
+ connstr_passwd( VALUE self, VALUE params)
368
+ {
369
+ static VALUE sym_password = Qundef;
370
+ VALUE pw;
371
+
372
+ if (sym_password == Qundef)
373
+ sym_password = ID2SYM( rb_intern( KEY_PASSWORD));
374
+ pw = rb_hash_aref( params, sym_password);
375
+ if (TYPE( pw) == T_STRING && RSTRING_LEN( pw) == 0) {
376
+ static ID id_password_q = 0;
377
+ VALUE pwobj;
378
+
379
+ if (id_password_q == 0)
380
+ id_password_q = rb_intern( "password?");
381
+ pwobj = Qundef;
382
+ if (rb_respond_to( self, id_password_q))
383
+ pwobj = self;
384
+ if (rb_respond_to( CLASS_OF( self), id_password_q))
385
+ pwobj = CLASS_OF( self);
386
+ if (pwobj != Qundef)
387
+ rb_hash_aset( params, sym_password,
388
+ rb_block_call( pwobj, id_password_q, 0, NULL,
389
+ &connstr_getparam, params));
390
+ }
391
+ }
392
+
393
+ VALUE connstr_getparam( VALUE yielded, VALUE params)
394
+ {
395
+ return rb_hash_aref( params, yielded);
396
+ }
397
+
398
+ /*
399
+ * call-seq:
400
+ * conn.close()
401
+ *
402
+ * Closes the backend connection.
403
+ */
404
+ VALUE
405
+ pgconn_close( VALUE self)
406
+ {
407
+ struct pgconn_data *c;
408
+
409
+ Data_Get_Struct( self, struct pgconn_data, c);
410
+ PQfinish( c->conn);
411
+ c->conn = NULL;
412
+ return Qnil;
413
+ }
414
+
415
+ /*
416
+ * call-seq:
417
+ * conn.reset()
418
+ *
419
+ * Resets the backend connection. This method closes the backend connection
420
+ * and tries to re-connect.
421
+ */
422
+ VALUE
423
+ pgconn_reset( VALUE self)
424
+ {
425
+ PQreset( get_pgconn( self)->conn);
426
+ return self;
427
+ }
428
+
429
+
430
+
431
+ /*
432
+ * call-seq:
433
+ * conn.client_encoding() -> str
434
+ *
435
+ * Returns the client encoding as a String.
436
+ */
437
+ VALUE
438
+ pgconn_client_encoding( VALUE self)
439
+ {
440
+ char *encoding = (char *) pg_encoding_to_char(
441
+ PQclientEncoding( get_pgconn( self)->conn));
442
+ return rb_tainted_str_new2( encoding);
443
+ }
444
+
445
+ /*
446
+ * call-seq:
447
+ * conn.set_client_encoding( encoding) -> nil
448
+ *
449
+ * Sets the client encoding to the +encoding+ string.
450
+ */
451
+ VALUE
452
+ pgconn_set_client_encoding( VALUE self, VALUE str)
453
+ {
454
+ StringValue( str);
455
+ if ((PQsetClientEncoding( get_pgconn( self)->conn, RSTRING_PTR( str))) == -1)
456
+ rb_raise( rb_ePgError, "Invalid encoding name %s", str);
457
+ return Qnil;
458
+ }
459
+
460
+
461
+ #ifdef RUBY_ENCODING
462
+
463
+ /*
464
+ * call-seq:
465
+ * conn.external_encoding -> enc
466
+ *
467
+ * Return the external encoding.
468
+ */
469
+ VALUE
470
+ pgconn_externalenc( VALUE self)
471
+ {
472
+ struct pgconn_data *c;
473
+
474
+ Data_Get_Struct( self, struct pgconn_data, c);
475
+ return c->external;
476
+ }
477
+
478
+ /*
479
+ * call-seq:
480
+ * conn.external_encoding = enc
481
+ *
482
+ * Set the external encoding.
483
+ */
484
+ VALUE
485
+ pgconn_set_externalenc( VALUE self, VALUE enc)
486
+ {
487
+ struct pgconn_data *c;
488
+ rb_encoding *e;
489
+
490
+ e = NIL_P( enc) ? rb_to_encoding( enc) : rb_default_external_encoding();
491
+ Data_Get_Struct( self, struct pgconn_data, c);
492
+ c->external = rb_enc_from_encoding( e);
493
+ }
494
+
495
+ /*
496
+ * call-seq:
497
+ * conn.internal_encoding -> enc
498
+ *
499
+ * Return the internal encoding.
500
+ */
501
+ VALUE
502
+ pgconn_internalenc( VALUE self)
503
+ {
504
+ struct pgconn_data *c;
505
+
506
+ Data_Get_Struct( self, struct pgconn_data, c);
507
+ return c->internal;
508
+ }
509
+
510
+ /*
511
+ * call-seq:
512
+ * conn.internal_encoding = enc
513
+ *
514
+ * Set the internal encoding.
515
+ */
516
+ VALUE
517
+ pgconn_set_internalenc( VALUE self, VALUE enc)
518
+ {
519
+ struct pgconn_data *c;
520
+ rb_encoding *e;
521
+
522
+ e = NIL_P( enc) ? rb_to_encoding( enc) : rb_default_internal_encoding();
523
+ Data_Get_Struct( self, struct pgconn_data, c);
524
+ c->internal = rb_enc_from_encoding( e);
525
+ }
526
+
527
+ #endif
528
+
529
+
530
+
531
+ /*
532
+ * call-seq:
533
+ * conn.protocol_version -> Integer
534
+ *
535
+ * The 3.0 protocol will normally be used when communicating with PostgreSQL
536
+ * 7.4 or later servers; pre-7.4 servers support only protocol 2.0. (Protocol
537
+ * 1.0 is obsolete and not supported by libpq.)
538
+ */
539
+ VALUE
540
+ pgconn_protocol_version( VALUE self)
541
+ {
542
+ return INT2FIX( PQprotocolVersion( get_pgconn( self)->conn));
543
+ }
544
+
545
+ /*
546
+ * call-seq:
547
+ * conn.server_version -> Integer
548
+ *
549
+ * The number is formed by converting the major, minor, and revision numbers
550
+ * into two-decimal-digit numbers and appending them together. For example,
551
+ * version 7.4.2 will be returned as 70402, and version 8.1 will be returned as
552
+ * 80100 (leading zeroes are not shown). Zero is returned if the connection is
553
+ * bad.
554
+ */
555
+ VALUE
556
+ pgconn_server_version( VALUE self)
557
+ {
558
+ return INT2FIX( PQserverVersion( get_pgconn( self)->conn));
559
+ }
560
+
561
+
562
+ /*
563
+ * call-seq:
564
+ * conn.db()
565
+ *
566
+ * Returns the connected database name.
567
+ */
568
+ VALUE
569
+ pgconn_dbname( VALUE self)
570
+ {
571
+ struct pgconn_data *c;
572
+ char *db;
573
+
574
+ c = get_pgconn( self);
575
+ db = PQdb( c->conn);
576
+ return db == NULL ? Qnil : pgconn_mkstring( c, db);
577
+ }
578
+
579
+ /*
580
+ * call-seq:
581
+ * conn.host()
582
+ *
583
+ * Returns the connected server name.
584
+ */
585
+ VALUE
586
+ pgconn_host( VALUE self)
587
+ {
588
+ struct pgconn_data *c;
589
+ char *host;
590
+
591
+ c = get_pgconn( self);
592
+ host = PQhost( c->conn);
593
+ return host == NULL ? Qnil : pgconn_mkstring( c, host);
594
+ }
595
+
596
+ /*
597
+ * call-seq:
598
+ * conn.options()
599
+ *
600
+ * Returns backend option string.
601
+ */
602
+ VALUE
603
+ pgconn_options( VALUE self)
604
+ {
605
+ struct pgconn_data *c;
606
+ char *options;
607
+
608
+ c = get_pgconn( self);
609
+ options = PQoptions( c->conn);
610
+ return options == NULL ? Qnil : pgconn_mkstring( c, options);
611
+ }
612
+
613
+ /*
614
+ * call-seq:
615
+ * conn.port()
616
+ *
617
+ * Returns the connected server port number.
618
+ */
619
+ VALUE
620
+ pgconn_port( VALUE self)
621
+ {
622
+ char* port = PQport( get_pgconn( self)->conn);
623
+ return port == NULL ? Qnil : INT2FIX( atol( port));
624
+ }
625
+
626
+ /*
627
+ * call-seq:
628
+ * conn.tty()
629
+ *
630
+ * Returns the connected pgtty.
631
+ */
632
+ VALUE
633
+ pgconn_tty( VALUE self)
634
+ {
635
+ struct pgconn_data *c;
636
+ char *tty;
637
+
638
+ c = get_pgconn( self);
639
+ tty = PQtty( c->conn);
640
+ return tty == NULL ? Qnil : pgconn_mkstring( c, tty);
641
+ }
642
+
643
+ /*
644
+ * call-seq:
645
+ * conn.user()
646
+ *
647
+ * Returns the authenticated user name.
648
+ */
649
+ VALUE
650
+ pgconn_user( VALUE self)
651
+ {
652
+ struct pgconn_data *c;
653
+ char *user;
654
+
655
+ c = get_pgconn( self);
656
+ user = PQuser( c->conn);
657
+ return user == NULL ? Qnil : pgconn_mkstring( c, user);
658
+ }
659
+
660
+ /*
661
+ * call-seq:
662
+ * conn.status()
663
+ *
664
+ * This may return the values +CONNECTION_OK+ or +CONNECTION_BAD+.
665
+ */
666
+ VALUE
667
+ pgconn_status( VALUE self)
668
+ {
669
+ return INT2FIX( PQstatus( get_pgconn( self)->conn));
670
+ }
671
+
672
+ /*
673
+ * call-seq:
674
+ * conn.error()
675
+ *
676
+ * Returns the error message about connection.
677
+ */
678
+ VALUE
679
+ pgconn_error( VALUE self)
680
+ {
681
+ struct pgconn_data *c;
682
+ char *error;
683
+
684
+ c = get_pgconn( self);
685
+ error = PQerrorMessage( c->conn);
686
+ return error == NULL ? Qnil : pgconn_mkstring( c, error);
687
+ }
688
+
689
+
690
+
691
+ /*
692
+ * call-seq:
693
+ * conn.socket() -> io
694
+ *
695
+ * Returns the sockets IO object.
696
+ */
697
+ VALUE
698
+ pgconn_socket( VALUE self)
699
+ {
700
+ static ID id_new = 0;
701
+ int fd;
702
+
703
+ if (id_new == 0)
704
+ id_new = rb_intern( "new");
705
+
706
+ fd = PQsocket( get_pgconn( self)->conn);
707
+ return rb_funcall( rb_cIO, id_new, 1, INT2FIX( fd));
708
+ }
709
+
710
+
711
+ /*
712
+ * call-seq:
713
+ * conn.trace( file)
714
+ * conn.trace( file) { ... }
715
+ *
716
+ * Enables tracing message passing between backend.
717
+ * The trace message will be written to the _file_ object,
718
+ * which is an instance of the class +File+ (or at least +IO+).
719
+ *
720
+ * In case a block is given +untrace+ will be called automatically.
721
+ */
722
+ VALUE
723
+ pgconn_trace( int argc, VALUE *argv, VALUE self)
724
+ {
725
+ VALUE file;
726
+ #ifdef HAVE_FUNC_RB_IO_STDIO_FILE
727
+ rb_io_t *fp;
728
+ #else
729
+ OpenFile* fp;
730
+ #define rb_io_stdio_file GetWriteFile
731
+ #endif
732
+
733
+ if (rb_scan_args( argc, argv, "01", &file) > 0) {
734
+ if (TYPE( file) != T_FILE)
735
+ rb_raise( rb_eArgError, "Not an IO object: %s",
736
+ StringValueCStr( file));
737
+ } else
738
+ file = rb_stdout;
739
+
740
+ GetOpenFile( file, fp);
741
+ PQtrace( get_pgconn( self)->conn, rb_io_stdio_file( fp));
742
+ return rb_block_given_p() ?
743
+ rb_ensure( rb_yield, Qnil, pgconn_untrace, self) : Qnil;
744
+ }
745
+
746
+ /*
747
+ * call-seq:
748
+ * conn.untrace()
749
+ *
750
+ * Disables the message tracing.
751
+ */
752
+ VALUE
753
+ pgconn_untrace( VALUE self)
754
+ {
755
+ PQuntrace( get_pgconn( self)->conn);
756
+ return Qnil;
757
+ }
758
+
759
+
760
+
761
+ /*
762
+ * call-seq:
763
+ * conn.on_notice { |message| ... }
764
+ *
765
+ * This method yields a PG::Result::Error object in case a nonfatal exception
766
+ * was raised.
767
+ *
768
+ * == Example
769
+ *
770
+ * conn.exec <<-EOT
771
+ * create or replace function noise() returns void as $$
772
+ * begin
773
+ * raise notice 'Hi!';
774
+ * end;
775
+ * $$ language plpgsql;
776
+ * EOT
777
+ * conn.on_notice { |e| puts e.inspect }
778
+ * conn.exec "select noise();"
779
+ */
780
+ VALUE
781
+ pgconn_on_notice( VALUE self)
782
+ {
783
+ struct pgconn_data *c;
784
+
785
+ Data_Get_Struct( self, struct pgconn_data, c);
786
+ if (PQsetNoticeReceiver( c->conn, NULL, NULL) != &notice_receiver) {
787
+ PQsetNoticeReceiver( c->conn, &notice_receiver, (void *) c);
788
+ }
789
+ c->notice = rb_block_given_p() ? rb_block_proc() : Qnil;
790
+ return self;
791
+ }
792
+
793
+ void
794
+ notice_receiver( void *self, const PGresult *result)
795
+ {
796
+ struct pgconn_data *c;
797
+
798
+ c = (struct pgconn_data *) self;
799
+ if (c->notice != Qnil) {
800
+ VALUE err;
801
+
802
+ err = pgconn_mkstring( c, PQresultErrorMessage( result));
803
+ rb_proc_call( c->notice, rb_ary_new3( 1l, err));
804
+ }
805
+ }
806
+
807
+
808
+
809
+
810
+ /********************************************************************
811
+ *
812
+ * Document-class: Pg::Conn::Failed
813
+ *
814
+ * Error while establishing a connection to the PostgreSQL server.
815
+ */
816
+
817
+ /********************************************************************
818
+ *
819
+ * Document-class: Pg::Conn::Invalid
820
+ *
821
+ * Invalid (closed) connection.
822
+ */
823
+
824
+
825
+ /********************************************************************
826
+ *
827
+ * Document-class: Pg::Conn
828
+ *
829
+ * The class to access a PostgreSQL database.
830
+ *
831
+ * == Example
832
+ *
833
+ * require "pgsql"
834
+ * conn = Pg::Conn.open :dbname => "test1"
835
+ * res = conn.exec "select * from mytable;"
836
+ *
837
+ * See the Pg::Result class for information on working with the results of a
838
+ * query.
839
+ */
840
+
841
+ void
842
+ Init_pgsql_conn( void)
843
+ {
844
+ #ifdef RDOC_NEEDS_THIS
845
+ rb_mPg = rb_define_module( "Pg");
846
+ #endif
847
+
848
+ rb_cPgConn = rb_define_class_under( rb_mPg, "Conn", rb_cObject);
849
+
850
+ rb_ePgConnFailed = rb_define_class_under( rb_cPgConn, "Failed", rb_ePgError);
851
+ rb_undef_method( CLASS_OF( rb_ePgConnFailed), "new");
852
+ rb_define_attr( rb_ePgConnFailed, "parameters", 1, 0);
853
+
854
+ rb_ePgConnInvalid = rb_define_class_under( rb_cPgConn, "Invalid", rb_ePgError);
855
+
856
+ rb_define_alloc_func( rb_cPgConn, pgconn_alloc);
857
+ rb_define_singleton_method( rb_cPgConn, "connect", pgconn_s_connect, -1);
858
+ rb_define_alias( rb_singleton_class( rb_cPgConn), "open", "connect");
859
+ rb_define_singleton_method( rb_cPgConn, "parse", pgconn_s_parse, 1);
860
+ rb_define_method( rb_cPgConn, "initialize", &pgconn_init, -1);
861
+ rb_define_method( rb_cPgConn, "close", &pgconn_close, 0);
862
+ rb_define_alias( rb_cPgConn, "finish", "close");
863
+ rb_define_method( rb_cPgConn, "reset", &pgconn_reset, 0);
864
+
865
+ rb_define_method( rb_cPgConn, "client_encoding", &pgconn_client_encoding, 0);
866
+ rb_define_method( rb_cPgConn, "set_client_encoding", &pgconn_set_client_encoding, 1);
867
+ #ifdef RUBY_ENCODING
868
+ rb_define_method( rb_cPgConn, "external_encoding", &pgconn_externalenc, 0);
869
+ rb_define_method( rb_cPgConn, "external_encoding=", &pgconn_set_externalenc, 1);
870
+ rb_define_method( rb_cPgConn, "internal_encoding", &pgconn_internalenc, 0);
871
+ rb_define_method( rb_cPgConn, "internal_encoding=", &pgconn_set_internalenc, 1);
872
+ #endif
873
+
874
+ rb_define_method( rb_cPgConn, "protocol_version", &pgconn_protocol_version, 0);
875
+ rb_define_method( rb_cPgConn, "server_version", &pgconn_server_version, 0);
876
+
877
+ rb_define_method( rb_cPgConn, "dbname", &pgconn_dbname, 0);
878
+ rb_define_alias( rb_cPgConn, "db", "dbname");
879
+ rb_define_method( rb_cPgConn, "host", &pgconn_host, 0);
880
+ rb_define_method( rb_cPgConn, "options", &pgconn_options, 0);
881
+ rb_define_method( rb_cPgConn, "port", &pgconn_port, 0);
882
+ rb_define_method( rb_cPgConn, "tty", &pgconn_tty, 0);
883
+ rb_define_method( rb_cPgConn, "user", &pgconn_user, 0);
884
+ rb_define_method( rb_cPgConn, "status", &pgconn_status, 0);
885
+ rb_define_method( rb_cPgConn, "error", &pgconn_error, 0);
886
+
887
+ #define CONN_DEF( c) rb_define_const( rb_cPgConn, #c, INT2FIX( CONNECTION_ ## c))
888
+ CONN_DEF( OK);
889
+ CONN_DEF( BAD);
890
+ #undef CONN_DEF
891
+
892
+ rb_define_method( rb_cPgConn, "socket", &pgconn_socket, 0);
893
+
894
+ rb_define_method( rb_cPgConn, "trace", &pgconn_trace, -1);
895
+ rb_define_method( rb_cPgConn, "untrace", &pgconn_untrace, 0);
896
+
897
+ rb_define_method( rb_cPgConn, "on_notice", &pgconn_on_notice, 0);
898
+
899
+ Init_pgsql_conn_quote();
900
+ Init_pgsql_conn_exec();
901
+ }
902
+