ruby-oci8 2.0.1 → 2.0.2

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.
@@ -3,7 +3,7 @@
3
3
  * attr.c
4
4
  *
5
5
  * $Author: kubo $
6
- * $Date: 2009-01-12 00:11:09 +0900 (Mon, 12 Jan 2009) $
6
+ * $Date: 2009-05-17 22:07:16 +0900 (Sun, 17 May 2009) $
7
7
  *
8
8
  * Copyright (C) 2002-2007 KUBO Takehiro <kubo@jiubao.org>
9
9
  */
@@ -106,7 +106,8 @@ static VALUE get_rowid_attr(rowid_arg_t *arg)
106
106
  * Oracle Server.
107
107
  */
108
108
  oci8_base_t *svc;
109
- oci8_exec_sql_var_t bind_vars[2];
109
+ oci8_exec_sql_var_t define_var;
110
+ oci8_exec_sql_var_t bind_var;
110
111
 
111
112
  /* search a connection from the handle */
112
113
  svc = base;
@@ -117,19 +118,19 @@ static VALUE get_rowid_attr(rowid_arg_t *arg)
117
118
  }
118
119
  }
119
120
  /* :strval */
120
- bind_vars[0].valuep = buf;
121
- bind_vars[0].value_sz = sizeof(buf);
122
- bind_vars[0].dty = SQLT_CHR;
123
- bind_vars[0].indp = NULL;
124
- bind_vars[0].alenp = &buflen;
121
+ define_var.valuep = buf;
122
+ define_var.value_sz = sizeof(buf);
123
+ define_var.dty = SQLT_CHR;
124
+ define_var.indp = NULL;
125
+ define_var.alenp = &buflen;
125
126
  /* :rowid */
126
- bind_vars[1].valuep = &arg->ridp;
127
- bind_vars[1].value_sz = sizeof(void *);
128
- bind_vars[1].dty = SQLT_RDD;
129
- bind_vars[1].indp = NULL;
130
- bind_vars[1].alenp = NULL;
127
+ bind_var.valuep = &arg->ridp;
128
+ bind_var.value_sz = sizeof(void *);
129
+ bind_var.dty = SQLT_RDD;
130
+ bind_var.indp = NULL;
131
+ bind_var.alenp = NULL;
131
132
  /* convert the rowid descriptor to a string value by querying Oracle server. */
132
- oci8_exec_sql((oci8_svcctx_t*)svc, "BEGIN :strval := :rowid; END;", 0, NULL, 2, bind_vars, 1);
133
+ oci8_exec_sql((oci8_svcctx_t*)svc, "SELECT :rid FROM dual", 1, &define_var, 1, &bind_var, 1);
133
134
  if (buflen == 0) {
134
135
  return Qnil;
135
136
  }
@@ -3,7 +3,7 @@
3
3
  * bind.c
4
4
  *
5
5
  * $Author: kubo $
6
- * $Date: 2009-02-10 22:50:40 +0900 (Tue, 10 Feb 2009) $
6
+ * $Date: 2009-05-17 22:07:16 +0900 (Sun, 17 May 2009) $
7
7
  *
8
8
  * Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
9
9
  */
@@ -46,7 +46,7 @@ static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE len
46
46
  } else {
47
47
  sz = NUM2INT(length);
48
48
  }
49
- if (sz <= 0) {
49
+ if (sz < 0) {
50
50
  rb_raise(rb_eArgError, "invalid bind length %d", sz);
51
51
  }
52
52
  sz += sizeof(sb4);
@@ -284,8 +284,8 @@ static VALUE bind_float_get(oci8_bind_t *obind, void *data, void *null_struct)
284
284
 
285
285
  static void bind_float_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
286
286
  {
287
- Check_Type(val, T_FLOAT);
288
- *(double*)data = RFLOAT_VALUE(val);
287
+ /* val is converted to Float if it isn't Float. */
288
+ *(double*)data = RFLOAT_VALUE(rb_Float(val));
289
289
  }
290
290
 
291
291
  static void bind_float_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
@@ -45,7 +45,7 @@ VALUE oci8_charset_id2name(VALUE svc, VALUE csid)
45
45
  char buf[OCI_NLS_MAXBUFSZ];
46
46
  sword rv;
47
47
 
48
- rv = OCINlsCharSetIdToName(oci8_envhp, TO_ORATEXT(buf), sizeof(buf), FIX2INT(csid));
48
+ rv = OCINlsCharSetIdToName(oci8_envhp, TO_ORATEXT(buf), sizeof(buf), (ub2)FIX2INT(csid));
49
49
  if (rv != OCI_SUCCESS) {
50
50
  return Qnil;
51
51
  }
@@ -1,10 +1,9 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
- env.c - part of ruby-oci8
4
-
5
- Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
6
-
7
- */
3
+ * env.c - part of ruby-oci8
4
+ *
5
+ * Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
6
+ */
8
7
  #include "oci8.h"
9
8
 
10
9
  #if !defined(RUBY_VM)
@@ -12,7 +11,37 @@
12
11
  #include <util.h>
13
12
  #endif
14
13
 
15
- OCIEnv *oci8_envhp;
14
+ #ifdef _WIN32
15
+ #ifdef HAVE_RUBY_WIN32_H
16
+ #include <ruby/win32.h> /* for rb_w32_getenv() */
17
+ #else
18
+ #include <win32/win32.h> /* for rb_w32_getenv() */
19
+ #endif
20
+ #endif
21
+
22
+ #ifdef HAVE_RUBY_UTIL_H
23
+ #include <ruby/util.h>
24
+ #endif
25
+
26
+ #ifdef RUBY_VM
27
+ ub4 oci8_env_mode = OCI_OBJECT | OCI_THREADED;
28
+ #else
29
+ ub4 oci8_env_mode = OCI_OBJECT;
30
+ #endif
31
+
32
+ OCIEnv *oci8_global_envhp;
33
+
34
+ OCIEnv *oci8_make_envhp(void)
35
+ {
36
+ sword rv;
37
+
38
+ rv = OCIEnvCreate(&oci8_global_envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
39
+ if (rv != OCI_SUCCESS) {
40
+ oci8_raise_init_error();
41
+ }
42
+ return oci8_global_envhp;
43
+ }
44
+
16
45
  #ifdef RUBY_VM
17
46
  /*
18
47
  * oci8_errhp is a thread local object in ruby 1.9.
@@ -53,17 +82,23 @@ OCIError *oci8_make_errhp(void)
53
82
  /*
54
83
  * oci8_errhp is global in ruby 1.8.
55
84
  */
56
- OCIError *oci8_errhp;
85
+ OCIError *oci8_global_errhp;
86
+
87
+ OCIError *oci8_make_errhp(void)
88
+ {
89
+ sword rv;
90
+
91
+ rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_global_errhp, OCI_HTYPE_ERROR, 0, NULL);
92
+ if (rv != OCI_SUCCESS)
93
+ oci8_env_raise(oci8_envhp, rv);
94
+ return oci8_global_errhp;
95
+ }
57
96
  #endif
58
97
 
59
98
  void Init_oci8_env(void)
60
99
  {
61
- sword rv;
62
100
  #ifdef RUBY_VM
63
- ub4 mode = OCI_OBJECT | OCI_THREADED;
64
101
  int error;
65
- #else
66
- ub4 mode = OCI_OBJECT;
67
102
  #endif
68
103
 
69
104
  #if !defined(RUBY_VM) && !defined(_WIN32)
@@ -85,23 +120,38 @@ void Init_oci8_env(void)
85
120
  }
86
121
  }
87
122
  #endif /* WIN32 */
88
- rv = OCIInitialize(mode, NULL, NULL, NULL, NULL);
89
- if (rv != OCI_SUCCESS) {
90
- oci8_raise_init_error();
91
- }
92
- rv = OCIEnvInit(&oci8_envhp, OCI_DEFAULT, 0, NULL);
93
- if (rv != OCI_SUCCESS) {
94
- oci8_raise_init_error();
123
+
124
+ /* workaround code.
125
+ *
126
+ * When ORACLE_HOME ends with '/' and the Oracle client is
127
+ * an instant client lower than 10.2.0.3, OCIEvnCreate()
128
+ * doesn't work even though the combination of OCIInitialize()
129
+ * and OCIEnvInit() works fine. Delete the last slash for
130
+ * a workaround.
131
+ */
132
+ if (oracle_client_version < ORAVERNUM(10, 2, 0, 3, 0)) {
133
+ #ifdef _WIN32
134
+ #define DIR_SEP '\\'
135
+ #else
136
+ #define DIR_SEP '/'
137
+ #endif
138
+ char *home = getenv("ORACLE_HOME");
139
+ if (home != NULL) {
140
+ size_t homelen = strlen(home);
141
+ if (homelen > 0 && home[homelen - 1] == DIR_SEP) {
142
+ home = ruby_strdup(home);
143
+ home[homelen - 1] = '\0';
144
+ ruby_setenv("ORACLE_HOME", home);
145
+ xfree(home);
146
+ }
147
+ }
95
148
  }
149
+
96
150
  #ifdef RUBY_VM
97
151
  id_thread_key = rb_intern("__oci8_errhp__");
98
152
  error = oci8_tls_key_init(&oci8_tls_key);
99
153
  if (error != 0) {
100
154
  rb_raise(rb_eRuntimeError, "Cannot create thread local key (errno = %d)", error);
101
155
  }
102
- #else /* RUBY_VM */
103
- rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_errhp, OCI_HTYPE_ERROR, 0, NULL);
104
- if (rv != OCI_SUCCESS)
105
- oci8_env_raise(oci8_envhp, rv);
106
156
  #endif
107
157
  }
@@ -157,7 +157,7 @@ static void set_backtrace_and_raise(VALUE exc, const char *file, int line)
157
157
  #endif
158
158
  backtrace = rb_funcall(rb_cObject, oci8_id_caller, 0);
159
159
  if (TYPE(backtrace) == T_ARRAY) {
160
- snprintf(errmsg, sizeof(errmsg), "%s:%d:in oci8lib.so", file, line);
160
+ snprintf(errmsg, sizeof(errmsg), "%s:%d:in " STRINGIZE(oci8lib) DLEXT, file, line);
161
161
  errmsg[sizeof(errmsg) - 1] = '\0';
162
162
  rb_ary_unshift(backtrace, rb_usascii_str_new_cstr(errmsg));
163
163
  rb_funcall(exc, oci8_id_set_backtrace, 1, backtrace);
@@ -61,7 +61,13 @@ funcs.keys.sort.each do |version|
61
61
  puts "checking for Oracle #{verstr} API - #{result}"
62
62
  break if result == 'fail'
63
63
  end
64
- $defs << "-DACTUAL_ORACLE_CLIENT_VERSION=#{format('0x%08x', oci_actual_client_version)}"
64
+
65
+ have_type('oratext', 'ociap.h')
66
+ have_type('OCIDateTime*', 'ociap.h')
67
+ have_type('OCIInterval*', 'ociap.h')
68
+ have_type('OCICallbackLobRead2', 'ociap.h')
69
+ have_type('OCICallbackLobWrite2', 'ociap.h')
70
+ have_type('OCIAdmin*', 'ociap.h')
65
71
 
66
72
  if with_config('oracle-version')
67
73
  oci_client_version = with_config('oracle-version').to_i
@@ -97,7 +103,6 @@ have_func("localtime_r")
97
103
  have_header("intern.h")
98
104
  have_header("util.h")
99
105
  # ruby 1.9 headers
100
- have_header("ruby/util.h")
101
106
  have_type('rb_encoding', ['ruby/ruby.h', 'ruby/encoding.h'])
102
107
 
103
108
  # $! in C API
@@ -122,6 +127,7 @@ else
122
127
  raise 'unsupported ruby version: ' + RUBY_VERSION
123
128
  end
124
129
  $defs << "-DInit_oci8lib=Init_#{so_basename}"
130
+ $defs << "-Doci8lib=#{so_basename}"
125
131
 
126
132
  create_header()
127
133
 
@@ -26,6 +26,7 @@ typedef struct {
26
26
  ub4 pos;
27
27
  int char_width;
28
28
  ub1 csfrm;
29
+ ub1 lobtype;
29
30
  enum state state;
30
31
  } oci8_lob_t;
31
32
 
@@ -149,6 +150,7 @@ static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm
149
150
  lob->pos = 0;
150
151
  lob->char_width = 1;
151
152
  lob->csfrm = csfrm;
153
+ lob->lobtype = lobtype;
152
154
  lob->state = S_NO_OPEN_CLOSE;
153
155
  oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
154
156
  if (!NIL_P(val)) {
@@ -360,8 +362,14 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
360
362
  }
361
363
  v = rb_ary_join(v, Qnil);
362
364
  OBJ_TAINT(v);
363
- rb_enc_associate(v, oci8_encoding);
364
- return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
365
+ if (lob->lobtype == OCI_TEMP_CLOB) {
366
+ /* set encoding */
367
+ rb_enc_associate(v, oci8_encoding);
368
+ return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
369
+ } else {
370
+ /* ASCII-8BIT */
371
+ return v;
372
+ }
365
373
  }
366
374
 
367
375
  static VALUE oci8_lob_write(VALUE self, VALUE data)
@@ -371,7 +379,11 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
371
379
  ub4 amt;
372
380
 
373
381
  lob_open(lob);
374
- OCI8StringValue(data);
382
+ if (lob->lobtype == OCI_TEMP_CLOB) {
383
+ OCI8StringValue(data);
384
+ } else {
385
+ StringValue(data);
386
+ }
375
387
  amt = RSTRING_LEN(data);
376
388
  oci_lc(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm));
377
389
  lob->pos += amt;
@@ -483,9 +495,15 @@ static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
483
495
  oci8_lob_t *lob = DATA_PTR(self);
484
496
 
485
497
  bfile_close(lob);
498
+ if (RSTRING_LEN(dir_alias) > UB2MAXVAL) {
499
+ rb_raise(rb_eRuntimeError, "dir_alias is too long.");
500
+ }
501
+ if (RSTRING_LEN(filename) > UB2MAXVAL) {
502
+ rb_raise(rb_eRuntimeError, "filename is too long.");
503
+ }
486
504
  oci_lc(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob,
487
- RSTRING_ORATEXT(dir_alias), RSTRING_LEN(dir_alias),
488
- RSTRING_ORATEXT(filename), RSTRING_LEN(filename)));
505
+ RSTRING_ORATEXT(dir_alias), (ub2)RSTRING_LEN(dir_alias),
506
+ RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename)));
489
507
  }
490
508
 
491
509
  static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
@@ -503,6 +521,7 @@ static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
503
521
  lob->pos = 0;
504
522
  lob->char_width = 1;
505
523
  lob->csfrm = SQLCS_IMPLICIT;
524
+ lob->lobtype = OCI_TEMP_BLOB;
506
525
  lob->state = S_BFILE_CLOSE;
507
526
  if (argc != 1) {
508
527
  OCI8SafeStringValue(dir_alias);
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * metadata.c
4
4
  *
5
- * Copyright (C) 2006-2007 KUBO Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2006-2009 KUBO Takehiro <kubo@jiubao.org>
6
6
  *
7
7
  * implement private methods of classes in OCI8::Metadata module.
8
8
  *
@@ -210,7 +210,7 @@ static VALUE metadata_get_oraint(VALUE self, VALUE idx)
210
210
  memset(&on, 0, sizeof(on));
211
211
  on.OCINumberPart[0] = size;
212
212
  memcpy(&on.OCINumberPart[1], value, size);
213
- return oci8_make_integer(&on);
213
+ return oci8_make_integer(&on, oci8_errhp);
214
214
  }
215
215
 
216
216
  static VALUE metadata_get_param(VALUE self, VALUE idx)
@@ -277,7 +277,7 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
277
277
  oci_lc(OCIAttrSet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &val, 0, OCI_ATTR_DESC_PUBLIC, oci8_errhp));
278
278
  }
279
279
  oci_lc(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
280
- objtype, OCI_DEFAULT, FIX2INT(type), desc->hp.dschp));
280
+ objtype, OCI_DEFAULT, (ub1)FIX2INT(type), desc->hp.dschp));
281
281
  oci_lc(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp));
282
282
  return oci8_metadata_create(parmhp, self, obj);
283
283
  }
@@ -1,5 +1,10 @@
1
1
  /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
2
  /*
3
+ * Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
4
+ */
5
+
6
+ /*
7
+ *
3
8
  * Document-class: OCI8::TDO
4
9
  *
5
10
  * OCI8::TDO is the class for Type Descriptor Object, which describe
@@ -157,11 +162,11 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
157
162
  return rb_str_new(TO_CHARPTR(OCIRawPtr(oci8_envhp, *(OCIRaw **)data)),
158
163
  OCIRawSize(oci8_envhp, *(OCIRaw **)data));
159
164
  case ATTR_OCINUMBER:
160
- return oci8_make_ocinumber((OCINumber *)data);
165
+ return oci8_make_ocinumber((OCINumber *)data, oci8_errhp);
161
166
  case ATTR_FLOAT:
162
- return oci8_make_float((OCINumber *)data);
167
+ return oci8_make_float((OCINumber *)data, oci8_errhp);
163
168
  case ATTR_INTEGER:
164
- return oci8_make_integer((OCINumber *)data);
169
+ return oci8_make_integer((OCINumber *)data, oci8_errhp);
165
170
  case ATTR_BINARY_DOUBLE:
166
171
  return rb_float_new(*(double*)data);
167
172
  case ATTR_BINARY_FLOAT:
@@ -431,10 +436,10 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
431
436
  break;
432
437
  case ATTR_OCINUMBER:
433
438
  case ATTR_FLOAT:
434
- oci8_set_ocinumber((OCINumber*)data, val);
439
+ oci8_set_ocinumber((OCINumber*)data, val, oci8_errhp);
435
440
  break;
436
441
  case ATTR_INTEGER:
437
- oci8_set_integer((OCINumber*)data, val);
442
+ oci8_set_integer((OCINumber*)data, val, oci8_errhp);
438
443
  break;
439
444
  case ATTR_BINARY_DOUBLE:
440
445
  *(double*)data = NUM2DBL(val);
@@ -17,6 +17,10 @@ extern rb_pid_t rb_w32_getpid(void);
17
17
  #endif
18
18
  #endif
19
19
 
20
+ #ifndef OCI_ATTR_CLIENT_IDENTIFIER
21
+ #define OCI_ATTR_CLIENT_IDENTIFIER 278
22
+ #endif
23
+
20
24
  /*
21
25
  * Document-class: OCI8
22
26
  *
@@ -538,11 +542,11 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
538
542
 
539
543
  if (have_OCIServerRelease) {
540
544
  /* Oracle 9i or later */
541
- oci_lc(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), svcctx->base.type, &version));
545
+ oci_lc(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type, &version));
542
546
  return UINT2NUM(version);
543
547
  } else {
544
548
  /* Oracle 8.x */
545
- oci_lc(OCIServerVersion(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), svcctx->base.type));
549
+ oci_lc(OCIServerVersion(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type));
546
550
  if ((p = strchr(buf, '.')) != NULL) {
547
551
  unsigned int major, minor, update, patch, port_update;
548
552
  while (p >= buf && *p != ' ') {
@@ -556,6 +560,85 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
556
560
  }
557
561
  }
558
562
 
563
+ /*
564
+ * call-seq:
565
+ * ping -> true or false
566
+ *
567
+ * Verifies that the Oracle connection is alive.
568
+ *
569
+ * 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=.
571
+ *
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.
574
+ *
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.
577
+ */
578
+ static VALUE oci8_ping(VALUE self)
579
+ {
580
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
581
+ sword rv;
582
+
583
+ if (have_OCIPing_nb) {
584
+ /* Oracle 10.2 or upper */
585
+ rv = OCIPing_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT);
586
+ } else {
587
+ /* Oracle 10.1 or lower */
588
+ rv = oci8_exec_sql(svcctx, "BEGIN NULL; END;", 0U, NULL, 0U, NULL, 0);
589
+ }
590
+ return rv == OCI_SUCCESS ? Qtrue : FALSE;
591
+ }
592
+
593
+ /*
594
+ * call-seq:
595
+ * client_identifier = string
596
+ *
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 ':'.
599
+ *
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.
603
+ *
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
+ */
607
+ static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
608
+ {
609
+ OCISession *sess = oci8_get_oci_session(self);
610
+ char *ptr;
611
+ ub4 size;
612
+
613
+ if (!NIL_P(val)) {
614
+ OCI8SafeStringValue(val);
615
+ ptr = RSTRING_PTR(val);
616
+ size = RSTRING_LEN(val);
617
+ } else {
618
+ ptr = "";
619
+ size = 0;
620
+ }
621
+ if (oracle_client_version >= 900) {
622
+ if (size > 0 && ptr[0] == ':') {
623
+ rb_raise(rb_eArgError, "client identifier should not start with ':'.");
624
+ }
625
+ oci_lc(OCIAttrSet(sess, OCI_HTYPE_SESSION, ptr,
626
+ size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp));
627
+ } else {
628
+ oci8_exec_sql_var_t bind_vars[1];
629
+
630
+ /* :client_id */
631
+ bind_vars[0].valuep = ptr;
632
+ bind_vars[0].value_sz = size;
633
+ bind_vars[0].dty = SQLT_CHR;
634
+ bind_vars[0].indp = NULL;
635
+ bind_vars[0].alenp = NULL;
636
+
637
+ oci8_exec_sql(oci8_get_svcctx(self), "BEGIN DBMS_SESSION.SET_IDENTIFIER(:client_id); END;", 0, NULL, 1, bind_vars, 1);
638
+ }
639
+ return val;
640
+ }
641
+
559
642
  VALUE Init_oci8(void)
560
643
  {
561
644
  cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class);
@@ -589,6 +672,8 @@ VALUE Init_oci8(void)
589
672
  rb_define_method(cOCI8, "break", oci8_break, 0);
590
673
  rb_define_method(cOCI8, "prefetch_rows=", oci8_set_prefetch_rows, 1);
591
674
  rb_define_private_method(cOCI8, "oracle_server_vernum", oci8_oracle_server_vernum, 0);
675
+ rb_define_method(cOCI8, "ping", oci8_ping, 0);
676
+ rb_define_method(cOCI8, "client_identifier=", oci8_set_client_identifier, 1);
592
677
  return cOCI8;
593
678
  }
594
679