pgsql 1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+