ruby-oci8 1.0.3 → 1.0.4

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 CHANGED
@@ -1,3 +1,60 @@
1
+ 2009-02-08 KUBO Takehiro <kubo@jiubao.org>
2
+ * NEWS: add changes between 1.0.3 and 1.0.4.
3
+ * VERSION: change version to 1.0.4.
4
+ * dist-files: add newly added file names which must be included
5
+ in gem or tar.gz packages.
6
+
7
+ 2009-02-01 KUBO Takehiro <kubo@jiubao.org>
8
+ * lib/dbd/OCI8.rb: add code for ruby-dbi 0.4 type conversion.
9
+ * test/test_dbi.rb: suppress deprecated warnings while running
10
+ test_bind_dbi_data_type.
11
+ * test/test_dbi_clob.rb: fix a problem when running this
12
+ file directly.
13
+
14
+ 2009-01-31 KUBO Takehiro <kubo@jiubao.org>
15
+ * ext/oci8/oraconf.rb: fix for Oracle 11.1.0.7.0 instant
16
+ client rpm package. The directory tree is a bit different
17
+ with that of 11.1.0.6.0 or earlier.
18
+ (reported by Luis Parravicini.)
19
+
20
+ 2009-01-31 KUBO Takehiro <kubo@jiubao.org>
21
+ * lib/DBD/OCI8/OCI8.rb: renamed to lib/dbd/OCI8.rb.
22
+ * lib/dbd/OCI8.rb: 1. renamed from lib/DBD/OCI8/OCI8.rb
23
+ 2. fix USED_DBD_VERSION from 0.2 to 0.4.
24
+ 3. add DBI::DBD::OCI8.driver_name
25
+ (changes for ruby-dbi 0.4 contributed by James Cao.)
26
+
27
+ 2008-12-30 KUBO Takehiro <kubo@jiubao.org>
28
+ * ext/oci8/handle.c, ext/oci8/oci8.h, ext/oci8/svcctx.c: add
29
+ OCISvcCtx.pid, which returns id of the process where the
30
+ OCISvcCtx is created.
31
+ * lib/oci8.rb.in: add check code to ensure that the process id
32
+ is not changed.
33
+
34
+ 2008-12-30 KUBO Takehiro <kubo@jiubao.org>
35
+ * ext/oci8/const.c, ext/oci8/handle.c: suppress compilation warnings.
36
+ (contributed by Daniel Berger)
37
+
38
+ 2008-12-30 KUBO Takehiro <kubo@jiubao.org>
39
+ * ext/oci8/oraconf.rb: add code to check the cpu type of Mac OS X
40
+ libclntsh.dylib.
41
+
42
+ 2008-12-14 KUBO Takehiro <kubo@jiubao.org>
43
+ * lib/oci8.rb.in:
44
+ 1. fix to fetch a rowid column as s String.
45
+ 2. change the return type of OCI8::Cursor#rowid from OCIRowid
46
+ to String. It is a local call on Oracle 9.0 or upper.
47
+ But on Oracle 8.x client, it needs one network roundtrip
48
+ to convert OCIRowid to String on server side.
49
+ 3. fix OCI8#describe_table to prevent OCIStillExecuting when
50
+ non-blocking mode is enabled and it needs a time to
51
+ retrieve table information.
52
+ * ext/oci8/extconf.rb, ext/oci8/oci8.c: add OCIRowid#to_s
53
+ when OCIRowidToChar() is available.
54
+ * test/test_all.rb, test/test_rowid.rb: add a rowid test case.
55
+ * test/test_dbi_clob.rb: fix to pass tests when the test directory
56
+ path is too long.
57
+
1
58
  2008-08-10 KUBO Takehiro <kubo@jiubao.org>
2
59
  * NEWS: add changes between 1.0.2 and 1.0.3.
3
60
  * VERSION: change version to 1.0.3.
@@ -12,7 +69,7 @@
12
69
  2008-08-09 KUBO Takehiro <kubo@jiubao.org>
13
70
  * ext/oci8/lob.c: fix OCILobLocator#getLength for a lob over 1GB,
14
71
  which affect OCI8::LOB#size and OCI8::LOB#read. fix
15
- OCILobLocator#read and OCILobLocator#write to set offset over 2BG,
72
+ OCILobLocator#read and OCILobLocator#write to set offset over 2GB,
16
73
  which affect OCI8::LOB#read and OCI8::LOB#write.
17
74
  (This probmem was reported by Jonathan Hadders.)
18
75
 
data/NEWS CHANGED
@@ -1,3 +1,41 @@
1
+ 1.0.4:
2
+
3
+ 1. [dbi] support ruby-dbi 0.4
4
+ (Thanks to James Cao and Peter Zingg.)
5
+
6
+ Ruby-dbi 0.4 is supported by DBD::OCI8 after 6 months from the
7
+ release of 0.4.
8
+
9
+ If you are using ruby-dbi 0.1.1, you need to copy dbd/OCI8.rb
10
+ to DBD/OCI8/OCI8.rb. The file itself works fine with ruby-dbi
11
+ 0.1.1, but the dbi cannot find the file by default.
12
+
13
+ 2. Rowid column data are fetched as a String by default.
14
+
15
+ 3. The return type of OCI8::Cursor#rowid is changed from OCIRowid
16
+ to String.
17
+
18
+ Note: It needs one network roundtrip to convert OCIRowid to
19
+ String on server side when using Oracle 8.x client.
20
+ On Oracle 9.0 or upper it is converted in the client side.
21
+
22
+ 4. An exception is raised if a connection is used in a process which is
23
+ different with a process to establish the connection.
24
+
25
+ If you encounter an exception "The connection cannot be reused in the
26
+ forked process," see the following link.
27
+
28
+ http://groups.google.com/group/phusion-passenger/browse_thread/thread/b00d4770bc1d00b8
29
+
30
+ 5. fix for 11.1.0.7.0 instant rpm package.
31
+ (reported by Luis Parravicini.)
32
+
33
+ The directory tree is a bit different with that of 11.1.0.6.0
34
+ or earlier.
35
+
36
+ 6. suppress compilation warnings.
37
+ (contributed by Daniel Berger)
38
+
1
39
  1.0.3:
2
40
 
3
41
  1. add workaround code for a losing character problem when reading CLOB.
@@ -22,7 +60,7 @@
22
60
  OraNumber#to_json is added for Rails.
23
61
 
24
62
  4. [dbi] fix a problem when using Oracle 8i and ruby-dbi.
25
- (reported by Glauco MagnelliRemi Gagnon.)
63
+ (reported by Glauco Magnelli.)
26
64
 
27
65
  1.0.2:
28
66
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.3
1
+ 1.0.4
data/dist-files CHANGED
@@ -39,7 +39,7 @@ ext/oci8/session.c
39
39
  ext/oci8/stmt.c
40
40
  ext/oci8/svcctx.c
41
41
  lib/oci8.rb.in
42
- lib/DBD/OCI8/OCI8.rb
42
+ lib/dbd/OCI8.rb
43
43
  support/README
44
44
  support/runit/assert.rb
45
45
  support/runit/cui/testrunner.rb
@@ -68,3 +68,4 @@ test/test_oci8.rb
68
68
  test/test_oradate.rb
69
69
  test/test_oranumber.rb
70
70
  test/test_metadata.rb
71
+ test/test_rowid.rb
data/ext/oci8/const.c CHANGED
@@ -45,7 +45,7 @@ static oci8_names_t oci8_typecode[] = {
45
45
  static VALUE oci8_make_names(oci8_names_t *names, size_t size)
46
46
  {
47
47
  volatile VALUE ary;
48
- int i;
48
+ unsigned int i;
49
49
 
50
50
  ary = rb_ary_new();
51
51
  for (i = 0;i < size;i++)
@@ -55,7 +55,7 @@ static VALUE oci8_make_names(oci8_names_t *names, size_t size)
55
55
 
56
56
  void Init_oci8_const(void)
57
57
  {
58
- int i;
58
+ unsigned int i;
59
59
 
60
60
  oci8_id_code = rb_intern("code");
61
61
  oci8_id_define_array = rb_intern("define_array");
data/ext/oci8/extconf.rb CHANGED
@@ -77,6 +77,8 @@ have_func("OCILobCreateTemporary")
77
77
  have_func("OCILobGetChunkSize")
78
78
  have_func("OCILobLocatorAssign")
79
79
 
80
+ have_func("OCIRowidToChar")
81
+
80
82
  $defs.push("-DHAVE_OCIRESET") unless /80./ =~ oraconf.version
81
83
 
82
84
  # Checking gcc or not
data/ext/oci8/handle.c CHANGED
@@ -10,10 +10,20 @@ See ((<Class Hierarchy>)).
10
10
  =end
11
11
  */
12
12
  #include "oci8.h"
13
+ #ifdef HAVE_UNISTD_H
14
+ #include <unistd.h> /* getpid() */
15
+ #endif
16
+
17
+ #ifdef WIN32
18
+ #ifndef getpid
19
+ extern rb_pid_t rb_w32_getpid(void);
20
+ #define getpid() rb_w32_getpid()
21
+ #endif
22
+ #endif
13
23
 
14
24
  static void oci8_handle_do_free(oci8_handle_t *h)
15
25
  {
16
- int i;
26
+ unsigned int i;
17
27
  if (h->type == 0) {
18
28
  return;
19
29
  }
@@ -104,7 +114,7 @@ VALUE oci8_s_new(VALUE self)
104
114
  static void oci8_handle_mark(oci8_handle_t *h)
105
115
  {
106
116
  oci8_bind_handle_t *bh;
107
- int i;
117
+ unsigned int i;
108
118
 
109
119
  switch (h->type) {
110
120
  case OCI_HTYPE_SVCCTX:
@@ -149,6 +159,7 @@ oci8_handle_t *oci8_make_handle(ub4 type, dvoid *hp, OCIError *errhp, oci8_handl
149
159
  break;
150
160
  case OCI_HTYPE_SVCCTX:
151
161
  obj = Data_Make_Struct(cOCISvcCtx, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
162
+ h->u.svcctx.pid = getpid();
152
163
  break;
153
164
  case OCI_HTYPE_STMT:
154
165
  obj = Data_Make_Struct(cOCIStmt, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
@@ -221,8 +232,8 @@ oci8_handle_t *oci8_make_handle(ub4 type, dvoid *hp, OCIError *errhp, oci8_handl
221
232
 
222
233
  void oci8_link(oci8_handle_t *parent, oci8_handle_t *child)
223
234
  {
224
- int i;
225
- int new_size;
235
+ unsigned int i;
236
+ int new_size, n;
226
237
 
227
238
  if (parent == NULL)
228
239
  return;
@@ -238,8 +249,8 @@ void oci8_link(oci8_handle_t *parent, oci8_handle_t *child)
238
249
  new_size = parent->size + CHILDREN_ARRAY_GROW_SIZE;
239
250
  parent->children = xrealloc(parent->children, sizeof(oci8_handle_t *) * new_size);
240
251
  parent->children[parent->size] = child;
241
- for (i = parent->size + 1;i < new_size;i++) {
242
- parent->children[i] = NULL;
252
+ for (n = parent->size + 1;n < new_size;n++) {
253
+ parent->children[n] = NULL;
243
254
  }
244
255
  parent->size = new_size;
245
256
  return;
@@ -248,7 +259,7 @@ void oci8_link(oci8_handle_t *parent, oci8_handle_t *child)
248
259
  void oci8_unlink(oci8_handle_t *self)
249
260
  {
250
261
  oci8_handle_t *parent = self->parent;
251
- int i;
262
+ unsigned int i;
252
263
 
253
264
  if (self->parent == NULL)
254
265
  return;
data/ext/oci8/oci8.c CHANGED
@@ -77,6 +77,8 @@ VALUE eOCISuccessWithInfo;
77
77
  VALUE cOraDate;
78
78
  VALUE cOraNumber;
79
79
 
80
+ static void Init_OCIRowid(void);
81
+
80
82
  void
81
83
  Init_oci8lib()
82
84
  {
@@ -131,7 +133,46 @@ Init_oci8lib()
131
133
  Init_ora_date();
132
134
  Init_ora_number();
133
135
 
136
+ Init_OCIRowid();
137
+
134
138
  #ifdef DEBUG_CORE_FILE
135
139
  signal(SIGSEGV, SIG_DFL);
136
140
  #endif
137
141
  }
142
+
143
+ #if defined(WIN32)
144
+ typedef sword (*OCIRowidToChar_func_t)(OCIRowid *rowidDesc, OraText *outbfp, ub2 *outbflp, OCIError *errhp);
145
+ static OCIRowidToChar_func_t OCIRowidToChar_func;
146
+ #define OCIRowidToChar OCIRowidToChar_func
147
+ #endif
148
+
149
+ #if defined(WIN32) || defined(HAVE_OCIROWIDTOCHAR)
150
+ static VALUE oci8_rowid_to_s(VALUE self)
151
+ {
152
+ oci8_handle_t *h;
153
+ char buf[64];
154
+ ub2 buflen = sizeof(buf);
155
+ sword rv;
156
+
157
+ Get_Handle(self, h);
158
+ rv = OCIRowidToChar(h->hp, (text*)buf, &buflen, h->errhp);
159
+ if (rv != OCI_SUCCESS)
160
+ oci8_raise(h->errhp, rv, NULL);
161
+ return rb_str_new(buf, buflen);
162
+ }
163
+ #endif
164
+
165
+ static void Init_OCIRowid(void)
166
+ {
167
+ #if defined(WIN32)
168
+ HANDLE hModule = GetModuleHandle("OCI.DLL");
169
+ if (hModule != NULL) {
170
+ OCIRowidToChar_func = (OCIRowidToChar_func_t)GetProcAddress(hModule, "OCIRowidToChar");
171
+ }
172
+ if (OCIRowidToChar_func != NULL) {
173
+ rb_define_method(cOCIRowid, "to_s", oci8_rowid_to_s, 0);
174
+ }
175
+ #elif defined(HAVE_OCIROWIDTOCHAR)
176
+ rb_define_method(cOCIRowid, "to_s", oci8_rowid_to_s, 0);
177
+ #endif
178
+ }
data/ext/oci8/oci8.h CHANGED
@@ -10,6 +10,14 @@
10
10
  #include "rubyio.h"
11
11
  #include "intern.h"
12
12
 
13
+ #ifndef rb_pid_t
14
+ #ifdef WIN32
15
+ #define rb_pid_t int
16
+ #else
17
+ #define rb_pid_t pid_t
18
+ #endif
19
+ #endif
20
+
13
21
  #include <stdio.h>
14
22
  #include <stdlib.h>
15
23
  #ifdef __cplusplus
@@ -134,6 +142,9 @@ struct oci8_handle {
134
142
  int char_width;
135
143
  } lob_locator;
136
144
  #endif
145
+ struct {
146
+ rb_pid_t pid;
147
+ } svcctx;
137
148
  } u;
138
149
  };
139
150
  typedef struct oci8_handle oci8_handle_t;
data/ext/oci8/oraconf.rb CHANGED
@@ -110,8 +110,23 @@ class MiniSOReader
110
110
  when "MZ"
111
111
  # Windows
112
112
  read_pe(f)
113
+ when "\x02\x10"
114
+ # HP-UX PA-RISC1.1
115
+ read_parisc(f)
116
+ when "\xfe\xed"
117
+ # Big-endian Mach-O File
118
+ read_mach_o_be(f)
119
+ when "\xce\xfa"
120
+ # 32-bit Little-endian Mach-O File
121
+ read_mach_o_le(f, 32)
122
+ when "\xcf\xfa"
123
+ # 64-bit Little-endian Mach-O File
124
+ read_mach_o_le(f, 64)
125
+ when "\xca\xfe"
126
+ # Universal binary
127
+ read_mach_o_unversal(f)
113
128
  else
114
- # HP-UX(32-bit), AIX, Mac OS X and Tru64
129
+ # AIX and Tru64
115
130
  raise format("unknown file header: %02x %02x", file_header[0], file_header[1])
116
131
  end
117
132
  ensure
@@ -202,6 +217,79 @@ class MiniSOReader
202
217
  raise "Invalid coff machine: #{machine}"
203
218
  end
204
219
  end
220
+
221
+ # HP-UX PA-RISC(32 bit)
222
+ def read_parisc(f)
223
+ # 0-1 system_id - CPU_PA_RISC1_1
224
+ @file_format = :pa_risc
225
+ # 2-3 a_magic - SHL_MAGIC
226
+ raise 'invalid a_magic' if f.read(2).unpack('n')[0] != 0x10e
227
+ @bits = 32
228
+ @endian = :big
229
+ @cpu = :parisc
230
+ end
231
+
232
+ # Big-endian Mach-O File
233
+ def read_mach_o_be(f)
234
+ @file_format = :mach_o
235
+ @endian = :big
236
+ case f.read(2)
237
+ when "\xfa\xce" # feedface
238
+ @cpu = :ppc
239
+ @bits = 32
240
+ when "\xfa\xcf" # feedfacf
241
+ @cpu = :ppc64
242
+ @bits = 64
243
+ else
244
+ raise "unknown file format"
245
+ end
246
+ end
247
+
248
+ def read_mach_o_le(f, bits)
249
+ @file_format = :mach_o
250
+ @endian = :little
251
+ raise 'unknown file format' if f.read(2) != "\xed\xfe"
252
+ case bits
253
+ when 32
254
+ @cpu = :i386
255
+ @bits = 32
256
+ when 64
257
+ @cpu = :x86_64
258
+ @bits = 64
259
+ end
260
+ end
261
+
262
+ def read_mach_o_unversal(f)
263
+ raise 'unknown file format' if f.read(2) != "\xba\xbe" # cafebabe
264
+ @file_format = :universal
265
+ nfat_arch = f.read(4).unpack('N')[0]
266
+ @cpu = []
267
+ @endian = []
268
+ @bits = []
269
+ nfat_arch.times do
270
+ case cputype = f.read(4).unpack('N')[0]
271
+ when 7
272
+ @cpu << :i386
273
+ @endian << :little
274
+ @bits << 32
275
+ when 7 + 0x01000000
276
+ @cpu << :x86_64
277
+ @endian << :little
278
+ @bits << 64
279
+ when 18
280
+ @cpu << :ppc
281
+ @endian << :big
282
+ @bits << 32
283
+ when 18 + 0x01000000
284
+ @cpu << :ppc64
285
+ @endian << :big
286
+ @bits << 64
287
+ else
288
+ raise "Unknown mach-o cputype: #{cputype}"
289
+ end
290
+ f.seek(4 * 4, IO::SEEK_CUR)
291
+ end
292
+ end
205
293
  end
206
294
 
207
295
  class OraConf
@@ -335,6 +423,39 @@ EOS
335
423
  when /darwin/
336
424
  @@ld_envs = %w[DYLD_LIBRARY_PATH]
337
425
  so_ext = 'dylib'
426
+ check_proc = Proc.new do |file|
427
+ is_32bit = [0].pack('l!').size == 4
428
+ is_big_endian = "\x01\x02".unpack('s') == 0x0102
429
+ if is_32bit
430
+ if is_big_endian
431
+ this_cpu = :ppc # 32-bit big-endian
432
+ else
433
+ this_cpu = :i386 # 32-bit little-endian
434
+ end
435
+ else
436
+ if is_big_endian
437
+ this_cpu = :ppc64 # 64-bit big-endian
438
+ else
439
+ this_cpu = :x86_64 # 64-bit little-endian
440
+ end
441
+ end
442
+ so = MiniSOReader.new(file)
443
+ if so.file_format == :universal
444
+ if so.cpu.include? this_cpu
445
+ true
446
+ else
447
+ puts " skip: #{file} is for #{so.cpu} cpu."
448
+ false
449
+ end
450
+ else
451
+ if so.cpu == this_cpu
452
+ true
453
+ else
454
+ puts " skip: #{file} is for #{so.cpu} cpu."
455
+ false
456
+ end
457
+ end
458
+ end
338
459
  end
339
460
 
340
461
  glob_name = "#{oci_basename}.#{so_ext}#{oci_glob_postfix}"
@@ -844,13 +965,21 @@ class OraConfIC < OraConf
844
965
  def initialize(ic_dir)
845
966
  init
846
967
 
847
- if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+\.\d+\.\d+\.\d+)\/client(64)?\/lib(?:64)?/
968
+ if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+(?:\.\d+)*)\/client(64)?\/lib(?:64)?/
848
969
  # rpm package
849
- # official x86 rpms:
970
+ # x86 rpms after 11.1.0.7.0:
971
+ # library: /usr/lib/oracle/X.X/client/lib/
972
+ # include: /usr/include/oracle/X.X/client/
973
+ #
974
+ # x86_64 rpms after 11.1.0.7.0:
975
+ # library: /usr/lib/oracle/X.X/client64/lib/
976
+ # include: /usr/include/oracle/X.X/client64/
977
+ #
978
+ # x86 rpms before 11.1.0.6.0:
850
979
  # library: /usr/lib/oracle/X.X.X.X/client/lib/
851
980
  # include: /usr/include/oracle/X.X.X.X/client/
852
981
  #
853
- # official x86_64 rpms:
982
+ # x86_64 rpms before 11.1.0.6.0:
854
983
  # library: /usr/lib/oracle/X.X.X.X/client64/lib/
855
984
  # include: /usr/include/oracle/X.X.X.X/client64/
856
985
  #
data/ext/oci8/svcctx.c CHANGED
@@ -180,6 +180,14 @@ static VALUE oci8_close_all_files(VALUE self)
180
180
  return self;
181
181
  }
182
182
 
183
+ static VALUE oci8_pid(VALUE self)
184
+ {
185
+ oci8_handle_t *h;
186
+
187
+ Get_Handle(self, h); /* 0 */
188
+ return INT2FIX(h->u.svcctx.pid);
189
+ }
190
+
183
191
  void Init_oci8_svcctx(void)
184
192
  {
185
193
  rb_define_method(cOCISvcCtx, "logoff", oci8_svcctx_logoff, 0);
@@ -196,6 +204,7 @@ void Init_oci8_svcctx(void)
196
204
  rb_define_method(cOCISvcCtx, "reset", oci8_reset, 0);
197
205
  #endif
198
206
  rb_define_method(cOCISvcCtx, "close_all_files", oci8_close_all_files, 0);
207
+ rb_define_method(cOCISvcCtx, "pid", oci8_pid, 0);
199
208
  }
200
209
 
201
210
  /*
@@ -42,7 +42,32 @@ module DBD # :nodoc:
42
42
  module OCI8
43
43
 
44
44
  VERSION = "0.1"
45
- USED_DBD_VERSION = "0.2"
45
+ USED_DBD_VERSION = "0.4"
46
+
47
+ def self.driver_name
48
+ "OCI8"
49
+ end
50
+
51
+ # type converstion handler to bind values. (ruby-dbi 0.4)
52
+ if DBI.const_defined?(:TypeUtil)
53
+ DBI::TypeUtil.register_conversion("OCI8") do |obj|
54
+ case obj
55
+ when ::TrueClass
56
+ ['1', false]
57
+ when ::FalseClass
58
+ ['0', false]
59
+ else
60
+ [obj, false]
61
+ end
62
+ end
63
+ end
64
+
65
+ # no type converstion is required for result set. (ruby-dbi 0.4)
66
+ class NoTypeConversion
67
+ def self.parse(obj)
68
+ obj
69
+ end
70
+ end
46
71
 
47
72
  module Util
48
73
 
@@ -134,6 +159,7 @@ module Util
134
159
  'nullable' => col.nullable?,
135
160
  'precision' => precision,
136
161
  'scale' => scale,
162
+ 'dbi_type' => NoTypeConversion,
137
163
  }
138
164
  end
139
165
  private :column_metadata_to_column_info
data/lib/oci8.rb.in CHANGED
@@ -351,7 +351,7 @@ class OCI8
351
351
  def describe_table(table_name)
352
352
  desc = @@env.alloc(OCIDescribe)
353
353
  desc.attrSet(OCI_ATTR_DESC_PUBLIC, -1)
354
- desc.describeAny(@svc, table_name.to_s, OCI_PTYPE_UNK)
354
+ do_ocicall(@ctx) { desc.describeAny(@svc, table_name.to_s, OCI_PTYPE_UNK) }
355
355
  param = desc.attrGet(OCI_ATTR_PARAM)
356
356
 
357
357
  case param.attrGet(OCI_ATTR_PTYPE)
@@ -679,6 +679,9 @@ class OCI8
679
679
  end
680
680
 
681
681
  def initialize(env, svc, ctx, stmt = nil)
682
+ if Process.pid != svc.pid
683
+ raise "The connection cannot be reused in the forked process."
684
+ end
682
685
  @env = env
683
686
  @svc = svc
684
687
  @ctx = ctx
@@ -811,8 +814,25 @@ class OCI8
811
814
  @stmttype = nil
812
815
  end # close
813
816
 
817
+ # Get the rowid of the last inserted/updated/deleted row.
814
818
  def rowid
815
- @stmt.attrGet(OCI_ATTR_ROWID)
819
+ # get the binary rowid
820
+ rid = @stmt.attrGet(OCI_ATTR_ROWID)
821
+ # convert it to a string rowid.
822
+ if rid.respond_to? :to_s
823
+ # (Oracle 9.0 or upper)
824
+ rid.to_s
825
+ else
826
+ # (Oracle 8.1 or lower)
827
+ stmt = @env.alloc(OCIStmt)
828
+ stmt.prepare('begin :1 := :2; end;')
829
+ b = stmt.bindByPos(1, OCI8::SQLT_CHR, 64)
830
+ stmt.bindByPos(2, OCI8::SQLT_RDD, rid)
831
+ do_ocicall(@ctx) { stmt.execute(@svc, 1, OCI_DEFAULT) }
832
+ str_rid = b.get()
833
+ stmt.free()
834
+ str_rid
835
+ end
816
836
  end
817
837
 
818
838
  def prefetch_rows=(rows)
@@ -899,6 +919,8 @@ class OCI8
899
919
  datatype = :nclob if p.attrGet(OCI_ATTR_CHARSET_FORM) == SQLCS_NCHAR
900
920
  when SQLT_BIN
901
921
  datasize *= 2 if OCI8::BindType::Mapping[datatype] == OCI8::BindType::String
922
+ when SQLT_RDD
923
+ datasize = 64
902
924
  end
903
925
 
904
926
  bind_or_define(:define, i, nil, datatype, datasize, precision, scale, true)
@@ -1210,7 +1232,7 @@ class OCI8
1210
1232
  # datatype type size prec scale
1211
1233
  # -------------------------------------------------
1212
1234
  # ROWID SQLT_RDD 4 0 0
1213
- BindType::Mapping[OCI8::SQLT_RDD] = BindType::OCIRowid
1235
+ BindType::Mapping[OCI8::SQLT_RDD] = BindType::String
1214
1236
 
1215
1237
  # datatype type size prec scale
1216
1238
  # -----------------------------------------------------
data/metaconfig CHANGED
@@ -120,8 +120,8 @@ install_files['oci8lib.so'] = <<-EOS
120
120
  install_files['oci8.rb'] = <<-EOS
121
121
  #{get_zcontent('lib/oci8.rb')}EOS
122
122
 
123
- install_files['DBD/OCI8/OCI8.rb'] = <<-EOS
124
- #{get_zcontent('lib/DBD/OCI8/OCI8.rb')}EOS
123
+ install_files['dbd/OCI8.rb'] = <<-EOS
124
+ #{get_zcontent('lib/dbd/OCI8.rb')}EOS
125
125
 
126
126
  begin
127
127
  installer = Installer.new(install_files)
data/test/test_all.rb CHANGED
@@ -18,6 +18,7 @@ require "#{srcdir}/test_break"
18
18
  require "#{srcdir}/test_oci8"
19
19
  require "#{srcdir}/test_connstr"
20
20
  require "#{srcdir}/test_metadata"
21
+ require "#{srcdir}/test_rowid"
21
22
 
22
23
  # Ruby/DBI
23
24
  begin
data/test/test_dbi.rb CHANGED
@@ -146,17 +146,27 @@ EOS
146
146
  end
147
147
 
148
148
  def test_bind_dbi_data_type
149
- inval = DBI::Date.new(2004, 3, 20)
150
- sth = @dbh.execute("BEGIN ? := ?; END;", DBI::Date, inval)
151
- outval = sth.func(:bind_value, 1)
152
- assert_instance_of(DBI::Date, outval)
153
- assert_equal(inval.to_time, outval.to_time)
149
+ begin
150
+ if DBI::VERSION >= '0.4.0'
151
+ # suppress deprecated warnings while running this test.
152
+ saved_action = Deprecated.action
153
+ Deprecated.set_action(Proc.new {})
154
+ end
155
+
156
+ inval = DBI::Date.new(2004, 3, 20)
157
+ sth = @dbh.execute("BEGIN ? := ?; END;", DBI::Date, inval)
158
+ outval = sth.func(:bind_value, 1)
159
+ assert_instance_of(DBI::Date, outval)
160
+ assert_equal(inval.to_time, outval.to_time)
154
161
 
155
- inval = DBI::Timestamp.new(2004, 3, 20, 18, 26, 33)
156
- sth = @dbh.execute("BEGIN ? := ?; END;", DBI::Timestamp, inval)
157
- outval = sth.func(:bind_value, 1)
158
- assert_instance_of(DBI::Timestamp, outval)
159
- assert_equal(inval.to_time, outval.to_time)
162
+ inval = DBI::Timestamp.new(2004, 3, 20, 18, 26, 33)
163
+ sth = @dbh.execute("BEGIN ? := ?; END;", DBI::Timestamp, inval)
164
+ outval = sth.func(:bind_value, 1)
165
+ assert_instance_of(DBI::Timestamp, outval)
166
+ assert_equal(inval.to_time, outval.to_time)
167
+ ensure
168
+ Deprecated.set_action(saved_action) if saved_action
169
+ end
160
170
  end
161
171
 
162
172
  def test_column_info
@@ -11,13 +11,14 @@ class TestDbiCLob < RUNIT::TestCase
11
11
  end
12
12
 
13
13
  def test_insert
14
- @dbh.do("DELETE FROM test_clob WHERE filename = :1", $lobfile)
14
+ filename = File.basename($lobfile)
15
+ @dbh.do("DELETE FROM test_clob WHERE filename = :1", filename)
15
16
 
16
17
  # insert an empty clob and get the rowid.
17
- rowid = @dbh.execute("INSERT INTO test_clob(filename, content) VALUES (:1, EMPTY_CLOB())", $lobfile) do |sth|
18
+ rowid = @dbh.execute("INSERT INTO test_clob(filename, content) VALUES (:1, EMPTY_CLOB())", filename) do |sth|
18
19
  sth.func(:rowid)
19
20
  end
20
- lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", $lobfile)[0]
21
+ lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", filename)[0]
21
22
  begin
22
23
  open($lobfile) do |f|
23
24
  while f.gets()
@@ -30,8 +31,9 @@ class TestDbiCLob < RUNIT::TestCase
30
31
  end
31
32
 
32
33
  def test_read
34
+ filename = File.basename($lobfile)
33
35
  test_insert() # first insert data.
34
- lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", $lobfile)[0]
36
+ lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", filename)[0]
35
37
  begin
36
38
  open($lobfile) do |f|
37
39
  while buf = lob.read($lobreadnum)
@@ -52,5 +54,5 @@ class TestDbiCLob < RUNIT::TestCase
52
54
  end
53
55
 
54
56
  if $0 == __FILE__
55
- RUNIT::CUI::TestRunner.run(TestCLob.suite())
57
+ RUNIT::CUI::TestRunner.run(TestDbiCLob.suite())
56
58
  end
@@ -0,0 +1,38 @@
1
+ require 'oci8'
2
+ require 'runit/testcase'
3
+ require 'runit/cui/testrunner'
4
+ require File.dirname(__FILE__) + '/config'
5
+
6
+ class TestRowid < RUNIT::TestCase
7
+
8
+ def setup
9
+ @conn = get_oci_connection()
10
+ end
11
+
12
+ def teardown
13
+ @conn.logoff
14
+ end
15
+
16
+ def test_rowid
17
+ drop_table('test_table')
18
+ sql = <<-EOS
19
+ CREATE TABLE test_table (N NUMBER(38))
20
+ EOS
21
+ @conn.exec(sql)
22
+ cursor = @conn.parse("INSERT INTO test_table values(1)");
23
+ cursor.exec
24
+ rid1 = cursor.rowid
25
+ assert_instance_of(String, rid1)
26
+ cursor.close
27
+ rid2 = nil
28
+ @conn.exec('select rowid from test_table where rowid = :1', rid1) do |row|
29
+ rid2 = row[0]
30
+ end
31
+ assert_equal(rid2, rid1)
32
+ drop_table('test_table')
33
+ end
34
+ end # TestRowid
35
+
36
+ if $0 == __FILE__
37
+ RUNIT::CUI::TestRunner.run(TestRowid.suite())
38
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - KUBO Takehiro
@@ -9,7 +9,7 @@ autorequire: oci8
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-08-10 00:00:00 +09:00
12
+ date: 2009-02-08 00:00:00 +09:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -63,7 +63,7 @@ files:
63
63
  - ext/oci8/stmt.c
64
64
  - ext/oci8/svcctx.c
65
65
  - lib/oci8.rb.in
66
- - lib/DBD/OCI8/OCI8.rb
66
+ - lib/dbd/OCI8.rb
67
67
  - support/README
68
68
  - support/runit/assert.rb
69
69
  - support/runit/cui/testrunner.rb
@@ -92,6 +92,7 @@ files:
92
92
  - test/test_oradate.rb
93
93
  - test/test_oranumber.rb
94
94
  - test/test_metadata.rb
95
+ - test/test_rowid.rb
95
96
  has_rdoc: true
96
97
  homepage: http://ruby-oci8.rubyforge.org
97
98
  post_install_message:
@@ -117,7 +118,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
118
  requirements: []
118
119
 
119
120
  rubyforge_project: ruby-oci8
120
- rubygems_version: 1.1.1
121
+ rubygems_version: 1.3.1
121
122
  signing_key:
122
123
  specification_version: 2
123
124
  summary: Ruby interface for Oracle using OCI8 API