ruby-oci8 2.0.2 → 2.0.3

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