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.
@@ -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));
@@ -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
- * Add a private method to test oci8_do_parse_connect_string().
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
- * connect to Oracle by _username_ and _password_.
129
- * set _dbname_ nil to connect the local database or TNS name to connect
130
- * via network. You can use the following syntax for _dbname_ if the client
131
- * library is Oracle 10g or upper.
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
- * //HOST_NAME_OR_IP:TNS_LISTENER_PORT/ORACLE_SID
158
+ * === connecting as a privileged user
134
159
  *
135
- * If you need DBA privilege, use :SYSDBA or :SYSOPER to _privilege_.
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
- * # connect to the local database.
138
- * # sqlplus scott/tiger
139
- * conn = OCI8.new("scott", "tiger")
164
+ * OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
165
+ * or
166
+ * OCI8.new('sys/change_on_install as sysdba')
140
167
  *
141
- * # connect via network with TNS name.
142
- * # sqlplus scott/tiger@orcl.world
143
- * conn = OCI8.new("scott", "tiger", "orcl.world")
168
+ * === external OS authentication
144
169
  *
145
- * # connect via network with database's host, port and SID.
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
- * # connect as SYSDBA
150
- * # sqlplus 'sys/change_on_install as sysdba'
151
- * conn = OCI8.new("sys", "change_on_install", nil, :SYSDBA)
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 = 0;
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
- * disconnect from Oracle. Uncommitted transaction will be
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
- * prepare the SQL statement and return an instance of OCI8::Cursor.
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
- * commit the transaction.
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
- * rollback the transaction.
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
- * return the status of blocking/non-blocking mode.
370
- * See non_blocking= also.
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
- * change the status of blocking/non-blocking mode. true for non-blocking
393
- * mode. false for blocking mode. The default is blocking.
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
- * When blocking mode, long-time SQL execution blocks the ruby process
396
- * itself even though multithread application because ruby's thread is
397
- * not native one.
438
+ * === ruby 1.8
439
+ * The default setting is +false+.
398
440
  *
399
- * when non-blocking mode, long-time SQL execution doesn't block the ruby
400
- * process. It only blocks the thread which executing the SQL statement.
401
- * But each SQL will need a bit more time because it checks the status by
402
- * polling.
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
- * return the state of the autocommit mode. The default value is
432
- * false. If true, the transaction is committed on every SQL executions.
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
- * change the status of the autocommit mode.
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 -> aFixnum (new in 0.1.16)
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
- * get the maximum fetch size for a LONG and LONG RAW column.
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 = aFixnum (new in 0.1.16)
514
+ * long_read_len = fixnum
474
515
  *
475
- * change the maximum fetch size for a LONG and LONG RAW column.
476
- * The default value is 65535.
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
- * cancel an executing SQL in an other thread.
497
- * See non_blocking= also.
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 = aFixnum (new in 0.1.14)
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
- * change the prefetch rows size. This reduces network round trips
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 -> Oracle server version number
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
- * Verifies that the Oracle connection is alive.
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. See: OCI8#client_identifier=.
621
+ * to the server if any exist.
571
622
  *
572
- * For Oracle 10.2 client or upper, a dummy round trip call is made by a newly
573
- * added OCI function in Oracle 10.2.
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
- * For Oracle 10.1 client or lower, a simple PL/SQL block "BEGIN NULL; END;"
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
- * Sets the CLIENT_IDENTIFIER column in the V$SESSION dictionary view.
598
- * This can be up to 64 bytes long. The first character should not be ':'.
662
+ * This executes the following PL/SQL block internally.
663
+ * The change is reflected immediately by a network round trip.
599
664
  *
600
- * If the Oracle client is 9i or upper, the change is not reflected to the
601
- * server immediately. It is postponed until the next round trip call for
602
- * example OCI8#exec, OCI8#ping, etc.
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
- if (oracle_client_version >= 900) {
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(sess, OCI_HTYPE_SESSION, ptr,
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), "BEGIN DBMS_SESSION.SET_IDENTIFIER(:client_id); END;", 0, NULL, 1, bind_vars, 1);
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