ruby-oci8 1.0.3 → 1.0.4

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