ruby-oci8 2.0.2 → 2.0.3
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/ChangeLog +121 -0
- data/Makefile +11 -4
- data/NEWS +126 -0
- data/VERSION +1 -1
- data/ext/oci8/.document +16 -1
- data/ext/oci8/apiwrap.yml +9 -0
- data/ext/oci8/attr.c +1 -1
- data/ext/oci8/bind.c +1 -38
- data/ext/oci8/extconf.rb +8 -9
- data/ext/oci8/lob.c +5 -3
- data/ext/oci8/object.c +12 -0
- data/ext/oci8/oci8.c +403 -115
- data/ext/oci8/oci8.h +4 -0
- data/ext/oci8/oci8lib.c +10 -1
- data/ext/oci8/ocidatetime.c +47 -5
- data/ext/oci8/ocinumber.c +254 -47
- data/ext/oci8/oraconf.rb +40 -11
- data/ext/oci8/oradate.c +1 -1
- data/lib/.document +0 -1
- data/lib/oci8.rb.in +1 -1
- data/lib/oci8/.document +2 -2
- data/lib/oci8/bindtype.rb +32 -8
- data/lib/oci8/compat.rb +5 -0
- data/lib/oci8/datetime.rb +284 -160
- data/lib/oci8/object.rb +18 -4
- data/lib/oci8/oci8.rb +24 -4
- data/test/test_appinfo.rb +34 -0
- data/test/test_clob.rb +13 -0
- data/test/test_datetime.rb +160 -7
- data/test/test_oci8.rb +31 -3
- data/test/test_oranumber.rb +12 -7
- metadata +3 -3
data/ext/oci8/object.c
CHANGED
@@ -37,6 +37,7 @@ enum {
|
|
37
37
|
ATTR_OCINUMBER,
|
38
38
|
ATTR_FLOAT,
|
39
39
|
ATTR_INTEGER,
|
40
|
+
ATTR_OCIDATE,
|
40
41
|
ATTR_BINARY_DOUBLE,
|
41
42
|
ATTR_BINARY_FLOAT,
|
42
43
|
ATTR_NAMED_TYPE,
|
@@ -167,6 +168,8 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
|
|
167
168
|
return oci8_make_float((OCINumber *)data, oci8_errhp);
|
168
169
|
case ATTR_INTEGER:
|
169
170
|
return oci8_make_integer((OCINumber *)data, oci8_errhp);
|
171
|
+
case ATTR_OCIDATE:
|
172
|
+
return oci8_make_ocidate((OCIDate *)data);
|
170
173
|
case ATTR_BINARY_DOUBLE:
|
171
174
|
return rb_float_new(*(double*)data);
|
172
175
|
case ATTR_BINARY_FLOAT:
|
@@ -309,6 +312,9 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
309
312
|
OCINumberSetZero(oci8_errhp, &cb_data.data.num);
|
310
313
|
cb_data.indp = &cb_data.ind;
|
311
314
|
break;
|
315
|
+
case ATTR_OCIDATE:
|
316
|
+
cb_data.indp = &cb_data.ind;
|
317
|
+
break;
|
312
318
|
case ATTR_BINARY_DOUBLE:
|
313
319
|
cb_data.data.dbl = 0.0;
|
314
320
|
cb_data.indp = &cb_data.ind;
|
@@ -370,6 +376,7 @@ static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data)
|
|
370
376
|
case ATTR_OCINUMBER:
|
371
377
|
case ATTR_FLOAT:
|
372
378
|
case ATTR_INTEGER:
|
379
|
+
case ATTR_OCIDATE:
|
373
380
|
case ATTR_BINARY_DOUBLE:
|
374
381
|
case ATTR_BINARY_FLOAT:
|
375
382
|
elem_ptr = &cb_data->data;
|
@@ -403,6 +410,7 @@ static VALUE set_coll_element_ensure(set_coll_element_cb_data_t *cb_data)
|
|
403
410
|
case ATTR_OCINUMBER:
|
404
411
|
case ATTR_FLOAT:
|
405
412
|
case ATTR_INTEGER:
|
413
|
+
case ATTR_OCIDATE:
|
406
414
|
case ATTR_BINARY_DOUBLE:
|
407
415
|
case ATTR_BINARY_FLOAT:
|
408
416
|
break;
|
@@ -441,6 +449,9 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
|
|
441
449
|
case ATTR_INTEGER:
|
442
450
|
oci8_set_integer((OCINumber*)data, val, oci8_errhp);
|
443
451
|
break;
|
452
|
+
case ATTR_OCIDATE:
|
453
|
+
oci8_set_ocidate((OCIDate*)data, val);
|
454
|
+
break;
|
444
455
|
case ATTR_BINARY_DOUBLE:
|
445
456
|
*(double*)data = NUM2DBL(val);
|
446
457
|
break;
|
@@ -592,6 +603,7 @@ void Init_oci_object(VALUE cOCI8)
|
|
592
603
|
rb_define_const(cOCI8TDO, "ATTR_OCINUMBER", INT2FIX(ATTR_OCINUMBER));
|
593
604
|
rb_define_const(cOCI8TDO, "ATTR_FLOAT", INT2FIX(ATTR_FLOAT));
|
594
605
|
rb_define_const(cOCI8TDO, "ATTR_INTEGER", INT2FIX(ATTR_INTEGER));
|
606
|
+
rb_define_const(cOCI8TDO, "ATTR_OCIDATE", INT2FIX(ATTR_OCIDATE));
|
595
607
|
rb_define_const(cOCI8TDO, "ATTR_BINARY_DOUBLE", INT2FIX(ATTR_BINARY_DOUBLE));
|
596
608
|
rb_define_const(cOCI8TDO, "ATTR_BINARY_FLOAT", INT2FIX(ATTR_BINARY_FLOAT));
|
597
609
|
rb_define_const(cOCI8TDO, "ATTR_NAMED_TYPE", INT2FIX(ATTR_NAMED_TYPE));
|
data/ext/oci8/oci8.c
CHANGED
@@ -20,25 +20,16 @@ extern rb_pid_t rb_w32_getpid(void);
|
|
20
20
|
#ifndef OCI_ATTR_CLIENT_IDENTIFIER
|
21
21
|
#define OCI_ATTR_CLIENT_IDENTIFIER 278
|
22
22
|
#endif
|
23
|
+
#ifndef OCI_ATTR_MODULE
|
24
|
+
#define OCI_ATTR_MODULE 366
|
25
|
+
#endif
|
26
|
+
#ifndef OCI_ATTR_ACTION
|
27
|
+
#define OCI_ATTR_ACTION 367
|
28
|
+
#endif
|
29
|
+
#ifndef OCI_ATTR_CLIENT_INFO
|
30
|
+
#define OCI_ATTR_CLIENT_INFO 368
|
31
|
+
#endif
|
23
32
|
|
24
|
-
/*
|
25
|
-
* Document-class: OCI8
|
26
|
-
*
|
27
|
-
* The class to access Oracle database server.
|
28
|
-
*
|
29
|
-
* example:
|
30
|
-
* # output the emp table's content as CSV format.
|
31
|
-
* conn = OCI8.new(username, password)
|
32
|
-
* conn.exec('select * from emp') do |row|
|
33
|
-
* puts row.join(',')
|
34
|
-
* end
|
35
|
-
*
|
36
|
-
* # execute PL/SQL block with bind variables.
|
37
|
-
* conn = OCI8.new(username, password)
|
38
|
-
* conn.exec('BEGIN procedure_name(:1, :2); END;',
|
39
|
-
* value_for_the_first_parameter,
|
40
|
-
* value_for_the_second_parameter)
|
41
|
-
*/
|
42
33
|
static VALUE cOCI8;
|
43
34
|
|
44
35
|
static void oci8_svcctx_free(oci8_base_t *base)
|
@@ -108,7 +99,16 @@ static void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pas
|
|
108
99
|
}
|
109
100
|
|
110
101
|
/*
|
111
|
-
*
|
102
|
+
* call-seq:
|
103
|
+
* parse_connect_string(string) -> [username, password, dbname, privilege]
|
104
|
+
*
|
105
|
+
* Extracts +username+, +password+, +dbname+ and +privilege+ from the specified +string+.
|
106
|
+
*
|
107
|
+
* example:
|
108
|
+
* "scott/tiger" -> ["scott", "tiger", nil, nil],
|
109
|
+
* "scott/tiger@oradb.example.com" -> ["scott", "tiger", "oradb.example.com", nil]
|
110
|
+
* "sys/change_on_install as sysdba" -> ["sys", "change_on_install", nil, :SYSDBA]
|
111
|
+
*
|
112
112
|
*/
|
113
113
|
static VALUE oci8_parse_connect_string(VALUE self, VALUE conn_str)
|
114
114
|
{
|
@@ -125,30 +125,68 @@ static VALUE oci8_parse_connect_string(VALUE self, VALUE conn_str)
|
|
125
125
|
* call-seq:
|
126
126
|
* new(username, password, dbname = nil, privilege = nil)
|
127
127
|
*
|
128
|
-
*
|
129
|
-
*
|
130
|
-
*
|
131
|
-
*
|
128
|
+
* Connects to an Oracle database server by +username+ and +password+
|
129
|
+
* at +dbname+ as +privilege+.
|
130
|
+
*
|
131
|
+
* === connecting to the local server
|
132
|
+
*
|
133
|
+
* Set +username+ and +password+ or pass "username/password" as a
|
134
|
+
* single argument.
|
135
|
+
*
|
136
|
+
* OCI8.new('scott', 'tiger')
|
137
|
+
* or
|
138
|
+
* OCI8.new('scott/tiger')
|
139
|
+
*
|
140
|
+
* === connecting to a remote server
|
141
|
+
*
|
142
|
+
* Set +username+, +password+ and +dbname+ or pass
|
143
|
+
* "username/password@dbname" as a single argument.
|
144
|
+
*
|
145
|
+
* OCI8.new('scott', 'tiger', 'orcl.world')
|
146
|
+
* or
|
147
|
+
* OCI8.new('scott/tiger@orcl.world')
|
148
|
+
*
|
149
|
+
* The +dbname+ is a net service name or an easy connectection
|
150
|
+
* identifier. The former is a name listed in the file tnsnames.ora.
|
151
|
+
* Ask to your DBA if you don't know what it is. The latter has the
|
152
|
+
* syntax as "//host:port/service_name".
|
153
|
+
*
|
154
|
+
* OCI8.new('scott', 'tiger', '//remote-host:1521/XE')
|
155
|
+
* or
|
156
|
+
* OCI8.new('scott/tiger@//remote-host:1521/XE')
|
132
157
|
*
|
133
|
-
*
|
158
|
+
* === connecting as a privileged user
|
134
159
|
*
|
135
|
-
*
|
160
|
+
* Set :SYSDBA or :SYSOPER to +privilege+, otherwise
|
161
|
+
* "username/password as sysdba" or "username/password as sysoper"
|
162
|
+
* as a single argument.
|
136
163
|
*
|
137
|
-
*
|
138
|
-
*
|
139
|
-
*
|
164
|
+
* OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
|
165
|
+
* or
|
166
|
+
* OCI8.new('sys/change_on_install as sysdba')
|
140
167
|
*
|
141
|
-
*
|
142
|
-
* # sqlplus scott/tiger@orcl.world
|
143
|
-
* conn = OCI8.new("scott", "tiger", "orcl.world")
|
168
|
+
* === external OS authentication
|
144
169
|
*
|
145
|
-
*
|
146
|
-
* # sqlplus scott/tiger@//localhost:1521/XE
|
147
|
-
* conn = OCI8.new("scott", "tiger", "//localhost:1521/XE")
|
170
|
+
* Set nil to +username+ and +password+, or "/" as a single argument.
|
148
171
|
*
|
149
|
-
*
|
150
|
-
*
|
151
|
-
*
|
172
|
+
* OCI8.new(nil, nil)
|
173
|
+
* or
|
174
|
+
* OCI8.new('/')
|
175
|
+
*
|
176
|
+
* To connect to a remote host:
|
177
|
+
*
|
178
|
+
* OCI8.new(nil, nil, 'dbname')
|
179
|
+
* or
|
180
|
+
* OCI8.new('/@dbname')
|
181
|
+
*
|
182
|
+
* === proxy authentication
|
183
|
+
*
|
184
|
+
* Enclose end user's username with square brackets and add it at the
|
185
|
+
* end of proxy user's username.
|
186
|
+
*
|
187
|
+
* OCI8.new('proxy_user_name[end_user_name]', 'proxy_password')
|
188
|
+
* or
|
189
|
+
* OCI8.new('proxy_user_name[end_user_name]/proxy_password')
|
152
190
|
*
|
153
191
|
*/
|
154
192
|
static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
|
@@ -254,7 +292,7 @@ static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
|
|
254
292
|
svcctx->pid = getpid();
|
255
293
|
svcctx->is_autocommit = 0;
|
256
294
|
#ifdef RUBY_VM
|
257
|
-
svcctx->non_blocking =
|
295
|
+
svcctx->non_blocking = 1;
|
258
296
|
#endif
|
259
297
|
svcctx->long_read_len = INT2FIX(65535);
|
260
298
|
return Qnil;
|
@@ -265,13 +303,8 @@ static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
|
|
265
303
|
* call-seq:
|
266
304
|
* logoff
|
267
305
|
*
|
268
|
-
*
|
306
|
+
* Disconnects from the Oracle server. The uncommitted transaction is
|
269
307
|
* rollbacked.
|
270
|
-
*
|
271
|
-
* example:
|
272
|
-
* conn = OCI8.new("scott", "tiger")
|
273
|
-
* ... do something ...
|
274
|
-
* conn.logoff
|
275
308
|
*/
|
276
309
|
static VALUE oci8_svcctx_logoff(VALUE self)
|
277
310
|
{
|
@@ -312,7 +345,7 @@ static VALUE oci8_svcctx_logoff(VALUE self)
|
|
312
345
|
* call-seq:
|
313
346
|
* parse(sql_text) -> an instance of OCI8::Cursor
|
314
347
|
*
|
315
|
-
*
|
348
|
+
* Prepares the SQL statement and returns a new OCI8::Cursor.
|
316
349
|
*/
|
317
350
|
static VALUE oci8_svcctx_parse(VALUE self, VALUE sql)
|
318
351
|
{
|
@@ -328,13 +361,7 @@ static VALUE oci8_svcctx_parse(VALUE self, VALUE sql)
|
|
328
361
|
* call-seq:
|
329
362
|
* commit
|
330
363
|
*
|
331
|
-
*
|
332
|
-
*
|
333
|
-
* example:
|
334
|
-
* conn = OCI8.new("scott", "tiger")
|
335
|
-
* conn.exec("UPDATE emp SET sal = sal * 1.1") # yahoo
|
336
|
-
* conn.commit
|
337
|
-
* conn.logoff
|
364
|
+
* Commits the transaction.
|
338
365
|
*/
|
339
366
|
static VALUE oci8_commit(VALUE self)
|
340
367
|
{
|
@@ -347,13 +374,7 @@ static VALUE oci8_commit(VALUE self)
|
|
347
374
|
* call-seq:
|
348
375
|
* rollback
|
349
376
|
*
|
350
|
-
*
|
351
|
-
*
|
352
|
-
* example:
|
353
|
-
* conn = OCI8.new("scott", "tiger")
|
354
|
-
* conn.exec("UPDATE emp SET sal = sal * 0.9") # boos
|
355
|
-
* conn.rollback
|
356
|
-
* conn.logoff
|
377
|
+
* Rollbacks the transaction.
|
357
378
|
*/
|
358
379
|
static VALUE oci8_rollback(VALUE self)
|
359
380
|
{
|
@@ -366,8 +387,10 @@ static VALUE oci8_rollback(VALUE self)
|
|
366
387
|
* call-seq:
|
367
388
|
* non_blocking? -> true or false
|
368
389
|
*
|
369
|
-
*
|
370
|
-
*
|
390
|
+
* Returns +true+ if the connection is in non-blocking mode, +false+
|
391
|
+
* otherwise.
|
392
|
+
*
|
393
|
+
* See also #non_blocking=.
|
371
394
|
*/
|
372
395
|
static VALUE oci8_non_blocking_p(VALUE self)
|
373
396
|
{
|
@@ -389,20 +412,38 @@ static VALUE oci8_non_blocking_p(VALUE self)
|
|
389
412
|
* call-seq:
|
390
413
|
* non_blocking = true or false
|
391
414
|
*
|
392
|
-
*
|
393
|
-
*
|
415
|
+
* Sets +true+ to enable non-blocking mode, +false+ otherwise.
|
416
|
+
* The default setting depends on the ruby version and ruby-oci8
|
417
|
+
* version.
|
418
|
+
*
|
419
|
+
* When the connection is in blocking mode (non_blocking = false),
|
420
|
+
* SQL executions block not only the thread, but also the ruby
|
421
|
+
* process. It makes the whole application stop while a SQL execution
|
422
|
+
* needs long time.
|
423
|
+
*
|
424
|
+
* When in non-blocking mode (non_blocking = true), SQL executions
|
425
|
+
* block only the thread. It does't prevent other threads.
|
426
|
+
* A SQL execution which blocks a thread can be canceled by
|
427
|
+
* OCI8#break.
|
428
|
+
*
|
429
|
+
* === ruby 1.9
|
430
|
+
* The default setting is +true+ if the ruby-oci8 version is 2.0.3 or
|
431
|
+
* upper, +false+ otherwise.
|
432
|
+
*
|
433
|
+
* Ruby-oci8 makes the connection non-blocking by releasing ruby
|
434
|
+
* interpreter's GVL (Global VM Lock or Giant VM Lock) while OCI
|
435
|
+
* functions which may need more than one network round trips are in
|
436
|
+
* execution.
|
394
437
|
*
|
395
|
-
*
|
396
|
-
*
|
397
|
-
* not native one.
|
438
|
+
* === ruby 1.8
|
439
|
+
* The default setting is +false+.
|
398
440
|
*
|
399
|
-
*
|
400
|
-
*
|
401
|
-
*
|
402
|
-
*
|
441
|
+
* Ruby-oci8 makes the connection non-blocking by polling the return
|
442
|
+
* values of OCI functions. When an OCI function returns
|
443
|
+
* OCI_STILL_EXECUTING, the thread sleeps for 10 milli seconds to make
|
444
|
+
* a time for other threads to run. The sleep time is doubled up to
|
445
|
+
* 640 milli seconds as the function returns the same value.
|
403
446
|
*
|
404
|
-
* You can cancel an executing SQL by using OCI8#break from another thread.
|
405
|
-
* The canceled thread raises OCIBreak exception.
|
406
447
|
*/
|
407
448
|
static VALUE oci8_set_non_blocking(VALUE self, VALUE val)
|
408
449
|
{
|
@@ -428,8 +469,8 @@ static VALUE oci8_set_non_blocking(VALUE self, VALUE val)
|
|
428
469
|
* call-seq:
|
429
470
|
* autocommit? -> true or false
|
430
471
|
*
|
431
|
-
*
|
432
|
-
*
|
472
|
+
* Returns +true+ if the connection is in autocommit mode, +false+
|
473
|
+
* otherwise. The default value is +false+.
|
433
474
|
*/
|
434
475
|
static VALUE oci8_autocommit_p(VALUE self)
|
435
476
|
{
|
@@ -441,13 +482,7 @@ static VALUE oci8_autocommit_p(VALUE self)
|
|
441
482
|
* call-seq:
|
442
483
|
* autocommit = true or false
|
443
484
|
*
|
444
|
-
*
|
445
|
-
*
|
446
|
-
* example:
|
447
|
-
* conn = OCI8.new("scott", "tiger")
|
448
|
-
* conn.autocommit = true
|
449
|
-
* ... do something ...
|
450
|
-
* conn.logoff
|
485
|
+
* Sets the autocommit mode. The default value is +false+.
|
451
486
|
*/
|
452
487
|
static VALUE oci8_set_autocommit(VALUE self, VALUE val)
|
453
488
|
{
|
@@ -458,9 +493,15 @@ static VALUE oci8_set_autocommit(VALUE self, VALUE val)
|
|
458
493
|
|
459
494
|
/*
|
460
495
|
* call-seq:
|
461
|
-
* long_read_len ->
|
496
|
+
* long_read_len -> fixnum
|
497
|
+
*
|
498
|
+
* Gets the maximum length in bytes to fetch a LONG or LONG RAW
|
499
|
+
* column. The default value is 65535.
|
462
500
|
*
|
463
|
-
*
|
501
|
+
* If the actual data length is longer than long_read_len,
|
502
|
+
* "ORA-01406: fetched column value was truncated" is raised.
|
503
|
+
*
|
504
|
+
* Note: long_read_len is also used for XMLTYPE data type in 2.0.
|
464
505
|
*/
|
465
506
|
static VALUE oci8_long_read_len(VALUE self)
|
466
507
|
{
|
@@ -470,16 +511,13 @@ static VALUE oci8_long_read_len(VALUE self)
|
|
470
511
|
|
471
512
|
/*
|
472
513
|
* call-seq:
|
473
|
-
* long_read_len =
|
514
|
+
* long_read_len = fixnum
|
474
515
|
*
|
475
|
-
*
|
476
|
-
*
|
516
|
+
* Sets the maximum length in bytes to fetch a LONG or LONG RAW
|
517
|
+
* column.
|
518
|
+
*
|
519
|
+
* See also #long_read_len
|
477
520
|
*
|
478
|
-
* example:
|
479
|
-
* conn = OCI8.new('scott', 'tiger'
|
480
|
-
* conn.long_read_len = 1000000
|
481
|
-
* cursor = con.exec('select content from articles where id = :1', 23478)
|
482
|
-
* row = cursor.fetch
|
483
521
|
*/
|
484
522
|
static VALUE oci8_set_long_read_len(VALUE self, VALUE val)
|
485
523
|
{
|
@@ -493,8 +531,9 @@ static VALUE oci8_set_long_read_len(VALUE self, VALUE val)
|
|
493
531
|
* call-seq:
|
494
532
|
* break
|
495
533
|
*
|
496
|
-
*
|
497
|
-
*
|
534
|
+
* Cancels the executing SQL.
|
535
|
+
*
|
536
|
+
* See also #non_blocking=.
|
498
537
|
*/
|
499
538
|
static VALUE oci8_break(VALUE self)
|
500
539
|
{
|
@@ -517,10 +556,14 @@ static VALUE oci8_break(VALUE self)
|
|
517
556
|
|
518
557
|
/*
|
519
558
|
* call-seq:
|
520
|
-
* prefetch_rows =
|
559
|
+
* prefetch_rows = number
|
560
|
+
*
|
561
|
+
* Sets the prefetch rows size. The default value is one.
|
562
|
+
* When a select statement is executed, the OCI library allocate
|
563
|
+
* prefetch buffer to reduce the number of network round trips by
|
564
|
+
* retrieving specified number of rows in one round trip.
|
521
565
|
*
|
522
|
-
*
|
523
|
-
* when fetching multiple rows.
|
566
|
+
* Note: Active record adaptors set 100 by default.
|
524
567
|
*/
|
525
568
|
static VALUE oci8_set_prefetch_rows(VALUE self, VALUE val)
|
526
569
|
{
|
@@ -530,8 +573,13 @@ static VALUE oci8_set_prefetch_rows(VALUE self, VALUE val)
|
|
530
573
|
|
531
574
|
/*
|
532
575
|
* call-seq:
|
533
|
-
* oracle_server_vernum ->
|
576
|
+
* oracle_server_vernum -> an integer
|
534
577
|
*
|
578
|
+
* <b>(new in 2.0.1)</b>
|
579
|
+
*
|
580
|
+
* Returns a numerical format of the Oracle server version.
|
581
|
+
*
|
582
|
+
* See also: #oracle_server_version
|
535
583
|
*/
|
536
584
|
static VALUE oci8_oracle_server_vernum(VALUE self)
|
537
585
|
{
|
@@ -564,16 +612,20 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
|
|
564
612
|
* call-seq:
|
565
613
|
* ping -> true or false
|
566
614
|
*
|
567
|
-
*
|
615
|
+
* <b>(new in 2.0.2)</b>
|
616
|
+
*
|
617
|
+
* Makes a round trip call to the server to confirm that the connection and
|
618
|
+
* the server are active.
|
568
619
|
*
|
569
620
|
* OCI8#ping also can be used to flush all the pending OCI client-side calls
|
570
|
-
* to the server if any exist.
|
621
|
+
* to the server if any exist.
|
571
622
|
*
|
572
|
-
*
|
573
|
-
* added OCI function
|
623
|
+
* === Oracle 10.2 client or upper
|
624
|
+
* A dummy round trip call is made by a newly added OCI function
|
625
|
+
* OCIPing[http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci16msc007.htm#sthref3540] in Oracle 10.2.
|
574
626
|
*
|
575
|
-
*
|
576
|
-
* is executed to make a round trip call.
|
627
|
+
* === Oracle 10.1 client or lower
|
628
|
+
* A simple PL/SQL block "BEGIN NULL; END;" is executed to make a round trip call.
|
577
629
|
*/
|
578
630
|
static VALUE oci8_ping(VALUE self)
|
579
631
|
{
|
@@ -592,23 +644,36 @@ static VALUE oci8_ping(VALUE self)
|
|
592
644
|
|
593
645
|
/*
|
594
646
|
* call-seq:
|
595
|
-
* client_identifier = string
|
647
|
+
* client_identifier = string or nil
|
648
|
+
*
|
649
|
+
* <b>(new in 2.0.3)</b>
|
650
|
+
*
|
651
|
+
* Sets the client ID. This information is stored in the V$SESSION
|
652
|
+
* view.
|
653
|
+
*
|
654
|
+
* === Oracle 9i client or upper
|
655
|
+
*
|
656
|
+
* This doesn't perform network round trips. The change is reflected
|
657
|
+
* to the server by the next round trip such as OCI8#exec, OCI8#ping,
|
658
|
+
* etc.
|
659
|
+
*
|
660
|
+
* === Oracle 8i client or lower
|
596
661
|
*
|
597
|
-
*
|
598
|
-
*
|
662
|
+
* This executes the following PL/SQL block internally.
|
663
|
+
* The change is reflected immediately by a network round trip.
|
599
664
|
*
|
600
|
-
*
|
601
|
-
*
|
602
|
-
*
|
665
|
+
* BEGIN
|
666
|
+
* DBMS_SESSION.SET_IDENTIFIER(:client_id);
|
667
|
+
* END;
|
668
|
+
*
|
669
|
+
* See {Oracle Manual: Oracle Database PL/SQL Packages and Types Reference}[http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_sessio.htm#i996935]
|
603
670
|
*
|
604
|
-
* This call is equivalent to "DBMS_SESSION.SET_IDENTIFIER(client_id VARCHAR2);"
|
605
|
-
* and available when the server is Oracle 9i or upper.
|
606
671
|
*/
|
607
672
|
static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
608
673
|
{
|
609
|
-
OCISession *sess = oci8_get_oci_session(self);
|
610
674
|
char *ptr;
|
611
675
|
ub4 size;
|
676
|
+
int use_attr_set = 1;
|
612
677
|
|
613
678
|
if (!NIL_P(val)) {
|
614
679
|
OCI8SafeStringValue(val);
|
@@ -618,11 +683,19 @@ static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
|
618
683
|
ptr = "";
|
619
684
|
size = 0;
|
620
685
|
}
|
621
|
-
|
686
|
+
|
687
|
+
if (oracle_client_version < ORAVER_9_0) {
|
688
|
+
use_attr_set = 0;
|
689
|
+
} else if (oracle_client_version < ORAVERNUM(9, 2, 0, 3, 0) && size == 0) {
|
690
|
+
/* Workaround for Bug 2449486 */
|
691
|
+
use_attr_set = 0;
|
692
|
+
}
|
693
|
+
|
694
|
+
if (use_attr_set) {
|
622
695
|
if (size > 0 && ptr[0] == ':') {
|
623
696
|
rb_raise(rb_eArgError, "client identifier should not start with ':'.");
|
624
697
|
}
|
625
|
-
oci_lc(OCIAttrSet(
|
698
|
+
oci_lc(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, ptr,
|
626
699
|
size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp));
|
627
700
|
} else {
|
628
701
|
oci8_exec_sql_var_t bind_vars[1];
|
@@ -634,13 +707,225 @@ static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
|
634
707
|
bind_vars[0].indp = NULL;
|
635
708
|
bind_vars[0].alenp = NULL;
|
636
709
|
|
637
|
-
oci8_exec_sql(oci8_get_svcctx(self),
|
710
|
+
oci8_exec_sql(oci8_get_svcctx(self),
|
711
|
+
"BEGIN\n"
|
712
|
+
" DBMS_SESSION.SET_IDENTIFIER(:client_id);\n"
|
713
|
+
"END;\n", 0, NULL, 1, bind_vars, 1);
|
714
|
+
}
|
715
|
+
return val;
|
716
|
+
}
|
717
|
+
|
718
|
+
/*
|
719
|
+
* call-seq:
|
720
|
+
* module = string or nil
|
721
|
+
*
|
722
|
+
* <b>(new in 2.0.3)</b>
|
723
|
+
*
|
724
|
+
* Sets the name of the current module. This information is
|
725
|
+
* stored in the V$SESSION view and is also stored in the V$SQL view
|
726
|
+
* and the V$SQLAREA view when a SQL statement is executed and the SQL
|
727
|
+
* statement is first parsed in the Oracle server.
|
728
|
+
*
|
729
|
+
* === Oracle 10g client or upper
|
730
|
+
*
|
731
|
+
* This doesn't perform network round trips. The change is reflected
|
732
|
+
* to the server by the next round trip such as OCI8#exec, OCI8#ping,
|
733
|
+
* etc.
|
734
|
+
*
|
735
|
+
* === Oracle 9i client or lower
|
736
|
+
*
|
737
|
+
* This executes the following PL/SQL block internally.
|
738
|
+
* The change is reflected immediately by a network round trip.
|
739
|
+
*
|
740
|
+
* DECLARE
|
741
|
+
* action VARCHAR2(32);
|
742
|
+
* BEGIN
|
743
|
+
* -- retrieve action name.
|
744
|
+
* SELECT SYS_CONTEXT('USERENV','ACTION') INTO action FROM DUAL;
|
745
|
+
* -- change module name without modifying the action name.
|
746
|
+
* DBMS_APPLICATION_INFO.SET_MODULE(:module, action);
|
747
|
+
* END;
|
748
|
+
*
|
749
|
+
* See {Oracle Manual: Oracle Database PL/SQL Packages and Types Reference}[http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_appinf.htm#i999254]
|
750
|
+
*
|
751
|
+
*/
|
752
|
+
static VALUE oci8_set_module(VALUE self, VALUE val)
|
753
|
+
{
|
754
|
+
char *ptr;
|
755
|
+
ub4 size;
|
756
|
+
|
757
|
+
if (!NIL_P(val)) {
|
758
|
+
OCI8SafeStringValue(val);
|
759
|
+
ptr = RSTRING_PTR(val);
|
760
|
+
size = RSTRING_LEN(val);
|
761
|
+
} else {
|
762
|
+
ptr = "";
|
763
|
+
size = 0;
|
764
|
+
}
|
765
|
+
if (oracle_client_version >= ORAVER_10_1) {
|
766
|
+
/* Oracle 10g or upper */
|
767
|
+
oci_lc(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, ptr,
|
768
|
+
size, OCI_ATTR_MODULE, oci8_errhp));
|
769
|
+
} else {
|
770
|
+
/* Oracle 9i or lower */
|
771
|
+
oci8_exec_sql_var_t bind_vars[1];
|
772
|
+
|
773
|
+
/* :module */
|
774
|
+
bind_vars[0].valuep = ptr;
|
775
|
+
bind_vars[0].value_sz = size;
|
776
|
+
bind_vars[0].dty = SQLT_CHR;
|
777
|
+
bind_vars[0].indp = NULL;
|
778
|
+
bind_vars[0].alenp = NULL;
|
779
|
+
|
780
|
+
oci8_exec_sql(oci8_get_svcctx(self),
|
781
|
+
"DECLARE\n"
|
782
|
+
" action VARCHAR2(32);\n"
|
783
|
+
"BEGIN\n"
|
784
|
+
" SELECT SYS_CONTEXT('USERENV','ACTION') INTO action FROM DUAL;\n"
|
785
|
+
" DBMS_APPLICATION_INFO.SET_MODULE(:module, action);\n"
|
786
|
+
"END;\n", 0, NULL, 1, bind_vars, 1);
|
787
|
+
}
|
788
|
+
return self;
|
789
|
+
}
|
790
|
+
|
791
|
+
/*
|
792
|
+
* call-seq:
|
793
|
+
* action = string or nil
|
794
|
+
*
|
795
|
+
* <b>(new in 2.0.3)</b>
|
796
|
+
*
|
797
|
+
* Sets the name of the current action within the current module.
|
798
|
+
* This information is stored in the V$SESSION view and is also
|
799
|
+
* stored in the V$SQL view and the V$SQLAREA view when a SQL
|
800
|
+
* statement is executed and the SQL statement is first parsed
|
801
|
+
* in the Oracle server.
|
802
|
+
*
|
803
|
+
* === Oracle 10g client or upper
|
804
|
+
*
|
805
|
+
* This doesn't perform network round trips. The change is reflected
|
806
|
+
* to the server by the next round trip such as OCI8#exec, OCI8#ping,
|
807
|
+
* etc.
|
808
|
+
*
|
809
|
+
* === Oracle 9i client or lower
|
810
|
+
*
|
811
|
+
* This executes the following PL/SQL block internally.
|
812
|
+
* The change is reflected immediately by a network round trip.
|
813
|
+
*
|
814
|
+
* BEGIN
|
815
|
+
* DBMS_APPLICATION_INFO.SET_ACTION(:action);
|
816
|
+
* END;
|
817
|
+
*
|
818
|
+
* See {Oracle Manual: Oracle Database PL/SQL Packages and Types Reference}[http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_appinf.htm#i999254]
|
819
|
+
*
|
820
|
+
*/
|
821
|
+
static VALUE oci8_set_action(VALUE self, VALUE val)
|
822
|
+
{
|
823
|
+
char *ptr;
|
824
|
+
ub4 size;
|
825
|
+
|
826
|
+
if (!NIL_P(val)) {
|
827
|
+
OCI8SafeStringValue(val);
|
828
|
+
ptr = RSTRING_PTR(val);
|
829
|
+
size = RSTRING_LEN(val);
|
830
|
+
} else {
|
831
|
+
ptr = "";
|
832
|
+
size = 0;
|
833
|
+
}
|
834
|
+
if (oracle_client_version >= ORAVER_10_1) {
|
835
|
+
/* Oracle 10g or upper */
|
836
|
+
oci_lc(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, ptr,
|
837
|
+
size, OCI_ATTR_ACTION, oci8_errhp));
|
838
|
+
} else {
|
839
|
+
/* Oracle 9i or lower */
|
840
|
+
oci8_exec_sql_var_t bind_vars[1];
|
841
|
+
|
842
|
+
/* :action */
|
843
|
+
bind_vars[0].valuep = ptr;
|
844
|
+
bind_vars[0].value_sz = size;
|
845
|
+
bind_vars[0].dty = SQLT_CHR;
|
846
|
+
bind_vars[0].indp = NULL;
|
847
|
+
bind_vars[0].alenp = NULL;
|
848
|
+
|
849
|
+
oci8_exec_sql(oci8_get_svcctx(self),
|
850
|
+
"BEGIN\n"
|
851
|
+
" DBMS_APPLICATION_INFO.SET_ACTION(:action);\n"
|
852
|
+
"END;\n", 0, NULL, 1, bind_vars, 1);
|
853
|
+
}
|
854
|
+
return val;
|
855
|
+
}
|
856
|
+
|
857
|
+
/*
|
858
|
+
* call-seq:
|
859
|
+
* client_info = string or nil
|
860
|
+
*
|
861
|
+
* <b>(new in 2.0.3)</b>
|
862
|
+
*
|
863
|
+
* Sets additional information about the client application.
|
864
|
+
* This information is stored in the V$SESSION view.
|
865
|
+
*
|
866
|
+
* === Oracle 10g client or upper
|
867
|
+
*
|
868
|
+
* This doesn't perform network round trips. The change is reflected
|
869
|
+
* to the server by the next round trip such as OCI8#exec, OCI8#ping,
|
870
|
+
* etc.
|
871
|
+
*
|
872
|
+
* === Oracle 9i client or lower
|
873
|
+
*
|
874
|
+
* This executes the following PL/SQL block internally.
|
875
|
+
* The change is reflected immediately by a network round trip.
|
876
|
+
*
|
877
|
+
* BEGIN
|
878
|
+
* DBMS_APPLICATION_INFO.SET_CLIENT_INFO(:client_info);
|
879
|
+
* END;
|
880
|
+
*
|
881
|
+
* See {Oracle Manual: Oracle Database PL/SQL Packages and Types Reference}[http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_appinf.htm#CHEJCFGG]
|
882
|
+
*/
|
883
|
+
static VALUE oci8_set_client_info(VALUE self, VALUE val)
|
884
|
+
{
|
885
|
+
char *ptr;
|
886
|
+
ub4 size;
|
887
|
+
|
888
|
+
if (!NIL_P(val)) {
|
889
|
+
OCI8SafeStringValue(val);
|
890
|
+
ptr = RSTRING_PTR(val);
|
891
|
+
size = RSTRING_LEN(val);
|
892
|
+
} else {
|
893
|
+
ptr = "";
|
894
|
+
size = 0;
|
895
|
+
}
|
896
|
+
if (oracle_client_version >= ORAVER_10_1) {
|
897
|
+
/* Oracle 10g or upper */
|
898
|
+
oci_lc(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, ptr,
|
899
|
+
size, OCI_ATTR_CLIENT_INFO, oci8_errhp));
|
900
|
+
} else {
|
901
|
+
/* Oracle 9i or lower */
|
902
|
+
oci8_exec_sql_var_t bind_vars[1];
|
903
|
+
|
904
|
+
/* :client_info */
|
905
|
+
bind_vars[0].valuep = ptr;
|
906
|
+
bind_vars[0].value_sz = size;
|
907
|
+
bind_vars[0].dty = SQLT_CHR;
|
908
|
+
bind_vars[0].indp = NULL;
|
909
|
+
bind_vars[0].alenp = NULL;
|
910
|
+
|
911
|
+
oci8_exec_sql(oci8_get_svcctx(self),
|
912
|
+
"BEGIN\n"
|
913
|
+
" DBMS_APPLICATION_INFO.SET_CLIENT_INFO(:client_info);\n"
|
914
|
+
"END;\n", 0, NULL, 1, bind_vars, 1);
|
638
915
|
}
|
639
916
|
return val;
|
640
917
|
}
|
641
918
|
|
642
919
|
VALUE Init_oci8(void)
|
643
920
|
{
|
921
|
+
#if 0
|
922
|
+
/*
|
923
|
+
* OCIHandle is the abstract base class for all OCI handles and
|
924
|
+
* descriptors which are opaque data types of Oracle Call Interface.
|
925
|
+
*/
|
926
|
+
oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
|
927
|
+
cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle);
|
928
|
+
#endif
|
644
929
|
cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class);
|
645
930
|
|
646
931
|
oracle_client_vernum = INT2FIX(oracle_client_version);
|
@@ -674,6 +959,9 @@ VALUE Init_oci8(void)
|
|
674
959
|
rb_define_private_method(cOCI8, "oracle_server_vernum", oci8_oracle_server_vernum, 0);
|
675
960
|
rb_define_method(cOCI8, "ping", oci8_ping, 0);
|
676
961
|
rb_define_method(cOCI8, "client_identifier=", oci8_set_client_identifier, 1);
|
962
|
+
rb_define_method(cOCI8, "module=", oci8_set_module, 1);
|
963
|
+
rb_define_method(cOCI8, "action=", oci8_set_action, 1);
|
964
|
+
rb_define_method(cOCI8, "client_info=", oci8_set_client_info, 1);
|
677
965
|
return cOCI8;
|
678
966
|
}
|
679
967
|
|