ruby-oci8 2.2.3 → 2.2.12

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +427 -0
  3. data/NEWS +335 -42
  4. data/README.md +20 -9
  5. data/dist-files +9 -3
  6. data/docs/bind-array-to-in_cond.md +2 -2
  7. data/docs/conflicts-local-connections-and-processes.md +7 -4
  8. data/docs/hanging-after-inactivity.md +63 -0
  9. data/docs/install-binary-package.md +15 -11
  10. data/docs/install-full-client.md +18 -21
  11. data/docs/install-instant-client.md +45 -27
  12. data/docs/install-on-osx.md +31 -120
  13. data/docs/ldap-auth-and-function-interposition.md +123 -0
  14. data/docs/number-type-mapping.md +79 -0
  15. data/docs/platform-specific-issues.md +17 -50
  16. data/docs/report-installation-issue.md +3 -0
  17. data/docs/timeout-parameters.md +3 -0
  18. data/ext/oci8/apiwrap.c.tmpl +2 -5
  19. data/ext/oci8/apiwrap.rb +6 -1
  20. data/ext/oci8/apiwrap.yml +34 -22
  21. data/ext/oci8/attr.c +4 -2
  22. data/ext/oci8/bind.c +366 -6
  23. data/ext/oci8/connection_pool.c +3 -3
  24. data/ext/oci8/encoding.c +5 -5
  25. data/ext/oci8/env.c +8 -2
  26. data/ext/oci8/error.c +24 -16
  27. data/ext/oci8/extconf.rb +8 -4
  28. data/ext/oci8/hook_funcs.c +274 -61
  29. data/ext/oci8/lob.c +31 -75
  30. data/ext/oci8/metadata.c +2 -2
  31. data/ext/oci8/object.c +72 -27
  32. data/ext/oci8/oci8.c +45 -132
  33. data/ext/oci8/oci8.h +32 -88
  34. data/ext/oci8/oci8lib.c +178 -38
  35. data/ext/oci8/ocihandle.c +37 -37
  36. data/ext/oci8/ocinumber.c +23 -18
  37. data/ext/oci8/oraconf.rb +158 -339
  38. data/ext/oci8/oradate.c +19 -19
  39. data/ext/oci8/plthook.h +10 -0
  40. data/ext/oci8/plthook_elf.c +433 -268
  41. data/ext/oci8/plthook_osx.c +40 -9
  42. data/ext/oci8/plthook_win32.c +9 -0
  43. data/ext/oci8/stmt.c +52 -17
  44. data/ext/oci8/win32.c +4 -22
  45. data/lib/oci8/bindtype.rb +1 -15
  46. data/lib/oci8/check_load_error.rb +57 -10
  47. data/lib/oci8/cursor.rb +57 -25
  48. data/lib/oci8/metadata.rb +9 -1
  49. data/lib/oci8/object.rb +10 -0
  50. data/lib/oci8/oci8.rb +33 -28
  51. data/lib/oci8/oracle_version.rb +11 -1
  52. data/lib/oci8/properties.rb +22 -0
  53. data/lib/oci8/version.rb +1 -1
  54. data/lib/oci8.rb +48 -4
  55. data/lib/ruby-oci8.rb +0 -3
  56. data/pre-distclean.rb +1 -3
  57. data/ruby-oci8.gemspec +3 -8
  58. data/setup.rb +11 -2
  59. data/test/README.md +37 -0
  60. data/test/config.rb +1 -1
  61. data/test/setup_test_object.sql +21 -13
  62. data/test/setup_test_package.sql +59 -0
  63. data/test/test_all.rb +2 -0
  64. data/test/test_bind_boolean.rb +99 -0
  65. data/test/test_bind_integer.rb +47 -0
  66. data/test/test_break.rb +11 -9
  67. data/test/test_clob.rb +4 -16
  68. data/test/test_connstr.rb +29 -13
  69. data/test/test_datetime.rb +8 -3
  70. data/test/test_object.rb +27 -9
  71. data/test/test_oci8.rb +170 -46
  72. data/test/test_oranumber.rb +12 -6
  73. data/test/test_package_type.rb +15 -3
  74. data/test/test_properties.rb +17 -0
  75. metadata +40 -54
  76. data/docs/osx-install-dev-tools.png +0 -0
  77. data/test/README +0 -42
data/ext/oci8/oraconf.rb CHANGED
@@ -4,88 +4,37 @@ require 'mkmf'
4
4
  # compatibility for ruby-1.9
5
5
  RbConfig = Config unless defined? RbConfig
6
6
 
7
- module MiniRegistry
8
- class MiniRegistryError < StandardError
9
- attr_reader :api_name
10
- attr_reader :code
11
- def initialize(api_name, code)
12
- @api_name = api_name
13
- @code = code
14
- end
15
- end
16
- if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw32|bccwin32/
17
- # Windows
18
- require 'Win32API' # raise LoadError when UNIX.
19
-
20
- # I looked in Win32Module by MoonWolf <URL:http://www.moonwolf.com/ruby/>,
21
- # copy the minimum code and reorganize it.
22
- ERROR_SUCCESS = 0
23
- ERROR_FILE_NOT_FOUND = 2
24
- ERROR_NO_MORE_ITEMS = 259
25
-
26
- HKEY_LOCAL_MACHINE = 0x80000002
27
- KEY_ENUMERATE_SUB_KEYS = 0x0008
28
- KEY_QUERY_VALUE = 0x0001
29
- RegOpenKeyExA = Win32API.new('advapi32', 'RegOpenKeyExA', 'LPLLP', 'L')
30
- RegEnumKeyExA = Win32API.new('advapi32', 'RegEnumKeyExA', 'LLPPPPPP', 'L')
31
- RegQueryValueExA = Win32API.new('advapi32','RegQueryValueExA','LPPPPP','L')
32
- RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
33
-
34
- def self.get_str_value(hKey, name)
35
- lpcbData = [0].pack('L')
36
- code = RegQueryValueExA.call(hKey, name, nil, nil, nil, lpcbData)
37
- if code == ERROR_FILE_NOT_FOUND
38
- return nil
39
- elsif code != ERROR_SUCCESS
40
- raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
41
- end
42
- len = lpcbData.unpack('L')[0]
43
- lpType = [0].pack('L')
44
- lpData = "\0"*len
45
- lpcbData = [len].pack('L')
46
- code = RegQueryValueExA.call(hKey, name, nil, lpType, lpData, lpcbData)
47
- if code != ERROR_SUCCESS
48
- raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
49
- end
50
- lpData.unpack('Z*')[0]
51
- end
52
-
53
- def self.enum_homes
54
- phkResult = [0].pack('L')
55
- code = RegOpenKeyExA.call(HKEY_LOCAL_MACHINE, 'SOFTWARE\ORACLE', 0, 0x20019, phkResult)
56
- if code != ERROR_SUCCESS
57
- raise MiniRegistryError.new("Win32::RegOpenKeyExA", code)
58
- end
59
- hKey = phkResult.unpack('L')[0]
60
- idx = 0
61
- maxkeylen = 256
62
- loop do
63
- lpName = "\0" * maxkeylen
64
- lpcName = [maxkeylen].pack('L')
65
- code = RegEnumKeyExA.call(hKey, idx, lpName, lpcName, nil, nil, nil, nil);
66
- break if code == ERROR_NO_MORE_ITEMS
67
- if code != ERROR_SUCCESS
68
- RegCloseKey.call(hKey)
69
- raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
70
- end
71
- code = RegOpenKeyExA.call(hKey, lpName, 0, KEY_QUERY_VALUE, phkResult)
72
- if code != ERROR_SUCCESS
73
- RegCloseKey.call(hKey)
74
- raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
7
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/
8
+ # Windows
9
+ require 'win32/registry'
10
+ module Registry
11
+
12
+ class OracleHome
13
+ attr_reader :name
14
+ attr_reader :path
15
+ def initialize(name, path)
16
+ @name = name
17
+ @path = path
18
+ end
19
+ end
20
+
21
+ def self.oracle_homes
22
+ homes = []
23
+ Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Oracle') do |key|
24
+ key.each_key do |subkey_name|
25
+ subkey = key.open(subkey_name)
26
+ begin
27
+ homes << OracleHome.new(subkey['ORACLE_HOME_NAME'], subkey['ORACLE_HOME'].chomp('\\'))
28
+ rescue Win32::Registry::Error
29
+ # ignore errors
30
+ end
75
31
  end
76
- hSubkey = phkResult.unpack('L')[0]
77
-
78
- name = get_str_value(hSubkey, 'ORACLE_HOME_NAME')
79
- path = get_str_value(hSubkey, 'ORACLE_HOME')
80
- yield name, path
81
- RegCloseKey.call(hSubkey)
82
- idx += 1
83
32
  end
84
- RegCloseKey.call(hKey)
33
+ homes
85
34
  end
86
35
 
87
36
  end
88
- end # module MiniRegistry
37
+ end
89
38
 
90
39
  # minimal implementation to read information of a shared object.
91
40
  class MiniSOReader
@@ -94,6 +43,10 @@ class MiniSOReader
94
43
  attr_reader :endian
95
44
  attr_reader :bits
96
45
 
46
+ MACH_O_CPU_TYPE_I386 = 7
47
+ MACH_O_CPU_TYPE_X86_64 = 7 + 0x01000000
48
+ MACH_O_CPU_TYPE_ARM64 = 12 + 0x01000000
49
+
97
50
  def initialize(filename)
98
51
  f = open(filename, 'rb')
99
52
  begin
@@ -107,9 +60,6 @@ class MiniSOReader
107
60
  when "\x02\x10"
108
61
  # HP-UX PA-RISC1.1
109
62
  read_parisc(f)
110
- when "\xfe\xed"
111
- # Big-endian Mach-O File
112
- read_mach_o_be(f)
113
63
  when "\xce\xfa"
114
64
  # 32-bit Little-endian Mach-O File
115
65
  read_mach_o_le(f, 32)
@@ -118,10 +68,10 @@ class MiniSOReader
118
68
  read_mach_o_le(f, 64)
119
69
  when "\xca\xfe"
120
70
  # Universal binary
121
- read_mach_o_unversal(f)
71
+ read_mach_o_universal(f)
122
72
  else
123
73
  # AIX and Tru64
124
- raise format("unknown file header: %02x %02x", file_header[0].to_i, file_header[1].to_i)
74
+ raise format("unknown file header: %02x %02x (%s)", file_header[0].ord, file_header[1].ord, filename)
125
75
  end
126
76
  ensure
127
77
  f.close
@@ -225,22 +175,6 @@ class MiniSOReader
225
175
  @cpu = :parisc
226
176
  end
227
177
 
228
- # Big-endian Mach-O File
229
- def read_mach_o_be(f)
230
- @file_format = :mach_o
231
- @endian = :big
232
- case f.read(2)
233
- when "\xfa\xce" # feedface
234
- @cpu = :ppc
235
- @bits = 32
236
- when "\xfa\xcf" # feedfacf
237
- @cpu = :ppc64
238
- @bits = 64
239
- else
240
- raise "unknown file format"
241
- end
242
- end
243
-
244
178
  def read_mach_o_le(f, bits)
245
179
  @file_format = :mach_o
246
180
  @endian = :little
@@ -250,12 +184,20 @@ class MiniSOReader
250
184
  @cpu = :i386
251
185
  @bits = 32
252
186
  when 64
253
- @cpu = :x86_64
187
+ cputype = f.read(4).unpack('V')[0]
188
+ case cputype
189
+ when MACH_O_CPU_TYPE_X86_64
190
+ @cpu = :x86_64
191
+ when MACH_O_CPU_TYPE_ARM64
192
+ @cpu = :arm64
193
+ else
194
+ raise "unknown mach-o cpu type: #{cputype}"
195
+ end
254
196
  @bits = 64
255
197
  end
256
198
  end
257
199
 
258
- def read_mach_o_unversal(f)
200
+ def read_mach_o_universal(f)
259
201
  raise 'unknown file format' if f.read(2) != "\xba\xbe" # cafebabe
260
202
  @file_format = :universal
261
203
  nfat_arch = f.read(4).unpack('N')[0]
@@ -264,21 +206,17 @@ class MiniSOReader
264
206
  @bits = []
265
207
  nfat_arch.times do
266
208
  case cputype = f.read(4).unpack('N')[0]
267
- when 7
209
+ when MACH_O_CPU_TYPE_I386
268
210
  @cpu << :i386
269
211
  @endian << :little
270
212
  @bits << 32
271
- when 7 + 0x01000000
213
+ when MACH_O_CPU_TYPE_X86_64
272
214
  @cpu << :x86_64
273
215
  @endian << :little
274
216
  @bits << 64
275
- when 18
276
- @cpu << :ppc
277
- @endian << :big
278
- @bits << 32
279
- when 18 + 0x01000000
280
- @cpu << :ppc64
281
- @endian << :big
217
+ when MACH_O_CPU_TYPE_ARM64
218
+ @cpu << :arm64
219
+ @endian << :little
282
220
  @bits << 64
283
221
  else
284
222
  raise "Unknown mach-o cputype: #{cputype}"
@@ -301,7 +239,6 @@ class OraConf
301
239
  def self.get
302
240
  original_CFLAGS = $CFLAGS
303
241
  original_defs = $defs
304
- ic_dir = nil
305
242
  begin
306
243
  # check Oracle instant client
307
244
  if with_config('instant-client')
@@ -313,11 +250,17 @@ class OraConf
313
250
  =======================================================
314
251
  EOS
315
252
  end
316
- ic_dir = check_ic_dir
317
- if ic_dir
318
- OraConfIC.new(ic_dir)
253
+ inc, lib = dir_config('instant-client')
254
+ if inc && lib
255
+ OraConfIC.new(inc, lib)
319
256
  else
320
- OraConfFC.new()
257
+ base = guess_ic_dir
258
+ if base
259
+ inc, lib = guess_dirs_from_ic_base(base)
260
+ OraConfIC.new(inc, lib)
261
+ else
262
+ OraConfFC.new
263
+ end
321
264
  end
322
265
  rescue
323
266
  case ENV['LANG']
@@ -349,6 +292,44 @@ EOS
349
292
  end
350
293
  end
351
294
 
295
+ # Guess the include and directory paths from
296
+ def self.guess_dirs_from_ic_base(ic_dir)
297
+ if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+(?:\.\d+)*)\/client(64)?\/lib(?:64)?/
298
+ # rpm package
299
+ # x86 rpms after 11.1.0.7.0:
300
+ # library: /usr/lib/oracle/X.X/client/lib/
301
+ # include: /usr/include/oracle/X.X/client/
302
+ #
303
+ # x86_64 rpms after 11.1.0.7.0:
304
+ # library: /usr/lib/oracle/X.X/client64/lib/
305
+ # include: /usr/include/oracle/X.X/client64/
306
+ #
307
+ # x86 rpms before 11.1.0.6.0:
308
+ # library: /usr/lib/oracle/X.X.X.X/client/lib/
309
+ # include: /usr/include/oracle/X.X.X.X/client/
310
+ #
311
+ # x86_64 rpms before 11.1.0.6.0:
312
+ # library: /usr/lib/oracle/X.X.X.X/client64/lib/
313
+ # include: /usr/include/oracle/X.X.X.X/client64/
314
+ #
315
+ # third-party x86_64 rpms(*1):
316
+ # library: /usr/lib64/oracle/X.X.X.X/client/lib/
317
+ # or /usr/lib64/oracle/X.X.X.X/client/lib64/
318
+ # include: /usr/include/oracle/X.X.X.X/client/
319
+ #
320
+ # *1 These had been used before Oracle released official x86_64 rpms.
321
+ #
322
+ lib_dir = ic_dir
323
+ inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
324
+ else
325
+ # zip package
326
+ lib_dir = ic_dir
327
+ inc_dir = "#{ic_dir}/sdk/include"
328
+ end
329
+
330
+ [inc_dir, lib_dir]
331
+ end
332
+
352
333
  def self.ld_envs
353
334
  @@ld_envs
354
335
  end
@@ -367,8 +348,9 @@ EOS
367
348
  end
368
349
  end
369
350
 
370
- def self.check_ic_dir
371
- puts "checking for load library path... "
351
+ def self.guess_ic_dir
352
+ puts "attempting to locate oracle-instantclient..."
353
+ puts "checking load library path... "
372
354
  STDOUT.flush
373
355
 
374
356
  # get library load path names
@@ -384,13 +366,13 @@ EOS
384
366
  [nil].pack('P').size
385
367
  rescue ArgumentError
386
368
  # Rubinius 1.2.3 doesn't support Array#pack('P').
387
- # Use Fixnum#size, which returns the size of long.
369
+ # Use Integer#size, which returns the size of long.
388
370
  1.size
389
371
  end
390
372
  is_32bit = size_of_pointer == 4
391
373
  is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102
392
374
  case RUBY_PLATFORM
393
- when /mswin32|mswin64|cygwin|mingw32|bccwin32/
375
+ when /mswin32|mswin64|cygwin|mingw/
394
376
  oci_basename = 'oci'
395
377
  oci_glob_postfix = ''
396
378
  nls_data_basename = ['oraociei*', 'oraociicus*']
@@ -433,20 +415,13 @@ EOS
433
415
  end
434
416
  so_ext = 'sl'
435
417
  when /darwin/
436
- @@ld_envs = %w[DYLD_LIBRARY_PATH]
418
+ @@ld_envs = %w[OCI_DIR]
437
419
  so_ext = 'dylib'
438
420
  if is_32bit
439
- if is_big_endian
440
- this_cpu = :ppc # 32-bit big-endian
441
- else
442
- this_cpu = :i386 # 32-bit little-endian
443
- end
421
+ this_cpu = :i386 # 32-bit little-endian
444
422
  else
445
- if is_big_endian
446
- this_cpu = :ppc64 # 64-bit big-endian
447
- else
448
- this_cpu = :x86_64 # 64-bit little-endian
449
- end
423
+ require 'etc'
424
+ this_cpu = Etc.uname[:machine].to_sym
450
425
  end
451
426
  check_proc = Proc.new do |file|
452
427
  so = MiniSOReader.new(file)
@@ -520,49 +495,6 @@ EOS
520
495
  end
521
496
  end
522
497
  when /darwin/
523
- fallback_path = ENV['DYLD_FALLBACK_LIBRARY_PATH']
524
- if fallback_path.nil?
525
- puts " DYLD_FALLBACK_LIBRARY_PATH is not set."
526
- else
527
- puts " checking DYLD_FALLBACK_LIBRARY_PATH..."
528
- ld_path, file = check_lib_in_path(fallback_path, glob_name, check_proc)
529
- end
530
- if ld_path.nil?
531
- puts " checking OCI_DIR..."
532
- ld_path, file = check_lib_in_path(ENV['OCI_DIR'], glob_name, check_proc)
533
- if ld_path
534
- puts " checking dependent shared libraries in #{file}..."
535
- open("|otool -L #{file}") do |f|
536
- f.gets # discard the first line
537
- while line = f.gets
538
- line =~ /^\s+(\S+)/
539
- libname = $1
540
- case libname
541
- when /^@rpath\/libclntsh\.dylib/, /^@rpath\/libnnz\d\d\.dylib/, /^@loader_path\/libnnz\d\d\.dylib/
542
- # No need to check the real path.
543
- # The current instant client doesn't use @rpath or @loader_path.
544
- when /\/libclntsh\.dylib/, /\/libnnz\d\d.dylib/
545
- raise <<EOS unless File.exists?(libname)
546
- The output of "otool -L #{file}" is:
547
- | #{IO.readlines("|otool -L #{file}").join(' | ')}
548
- Ruby-oci8 doesn't work without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH
549
- because the dependent file "#{libname}" doesn't exist.
550
-
551
- If you need to use ruby-oci8 without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH,
552
- download "fix_oralib.rb" in https://github.com/kubo/fix_oralib_osx
553
- and execute it in the directory "#{File.dirname(file)}" as follows to fix the path.
554
-
555
- cd #{File.dirname(file)}
556
- curl -O https://raw.githubusercontent.com/kubo/fix_oralib_osx/master/fix_oralib.rb
557
- ruby fix_oralib.rb
558
-
559
- Note: DYLD_* environment variables are unavailable for security reasons on OS X 10.11 El Capitan.
560
- EOS
561
- end
562
- end
563
- end
564
- end
565
- end
566
498
  if ld_path.nil?
567
499
  fallback_path = ENV['DYLD_FALLBACK_LIBRARY_PATH']
568
500
  if fallback_path.nil?
@@ -573,17 +505,8 @@ EOS
573
505
  end
574
506
  if ld_path.nil?
575
507
  raise <<EOS
576
- Set the environment variable DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH or
577
- OCI_DIR to point to the Instant client directory.
578
-
579
- If DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH is set, the environment
580
- variable must be set at runtime also.
581
-
582
- If OCI_DIR is set, dependent shared library paths are checked. If the checking
583
- is passed, ruby-oci8 works without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH.
584
-
585
- Note: OCI_DIR should be absolute path.
586
- Note: DYLD_* environment variables are unavailable for security reasons on OS X 10.11 El Capitan.
508
+ Oracle instant client is not found.
509
+ You need to install Oracle instant client.
587
510
  EOS
588
511
  end
589
512
  end
@@ -607,8 +530,8 @@ EOS
607
530
  paths.split(File::PATH_SEPARATOR).each do |path|
608
531
  next if path.nil? or path == ''
609
532
  print " checking #{path}... "
610
- path.gsub!(/\\/, '/') if /mswin32|mswin64|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
611
- files = Dir.glob(File.join(path, glob_name))
533
+ path.gsub!(/\\/, '/') if /mswin32|mswin64|cygwin|mingw/ =~ RUBY_PLATFORM
534
+ files = Dir.glob(File.join(path, glob_name)).sort.reverse
612
535
  if files.empty?
613
536
  puts "no"
614
537
  next
@@ -635,7 +558,7 @@ EOS
635
558
  if try_run("int main() { return 0; }")
636
559
  puts "ok"
637
560
  else
638
- puts "ng"
561
+ puts "failed"
639
562
  raise "C compiler doesn't work correctly."
640
563
  end
641
564
  end # check_cc
@@ -681,21 +604,11 @@ EOS
681
604
  STDOUT.flush
682
605
  rubyhdrdir = RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG['archdir']
683
606
  unless File.exist?(rubyhdrdir + '/ruby.h')
684
- puts "ng"
685
- if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{RbConfig::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
686
- raise <<EOS
687
- #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
688
- Run the following commands to fix the problem.
689
-
690
- cd #{RbConfig::CONFIG['archdir']}
691
- sudo ln -s ../universal-darwin8.0/* ./
692
- EOS
693
- else
694
- raise <<EOS
607
+ puts "failed"
608
+ raise <<EOS
695
609
  #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
696
610
  Install the ruby development library.
697
611
  EOS
698
- end
699
612
  end
700
613
  puts "ok"
701
614
  $stdout.flush
@@ -711,11 +624,11 @@ EOS
711
624
  end
712
625
  end
713
626
 
714
- if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw32|bccwin32/ # when Windows
627
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/ # when Windows
715
628
 
716
629
  def get_libs(lib_dir)
717
630
  case RUBY_PLATFORM
718
- when /cygwin|x64-mingw32/
631
+ when /cygwin/
719
632
  regex = ([nil].pack('P').size == 8) ? / T (OCI\w+)/ : / T _(OCI\w+)/
720
633
  oci_funcs = YAML.load(open(File.dirname(__FILE__) + '/apiwrap.yml')).keys.collect do |func|
721
634
  func =~ /_nb$/ ? $` : func
@@ -734,22 +647,6 @@ EOS
734
647
  system(command)
735
648
  puts("done")
736
649
  "-L. -lOCI"
737
- when /bccwin32/
738
- # replace '/' to '\\' because bcc linker misunderstands
739
- # 'C:/foo/bar/OCI.LIB' as unknown option.
740
- lib = "#{lib_dir}/BORLAND/OCI.LIB"
741
- return lib.tr('/', '\\') if File.exist?(lib)
742
- raise <<EOS
743
- #{lib} does not exist.
744
-
745
- Your Oracle may not support Borland C++.
746
- If you want to run this module, run the following command at your own risk.
747
- cd #{lib_dir.tr('/', '\\')}
748
- mkdir Borland
749
- cd Borland
750
- coff2omf ..\\MSVC\\OCI.LIB OCI.LIB
751
- EOS
752
- exit 1
753
650
  else
754
651
  "\"#{lib_dir}/MSVC/OCI.LIB\""
755
652
  end
@@ -793,7 +690,7 @@ class OraConfFC < OraConf
793
690
  use_lib32 = false
794
691
  end
795
692
 
796
- if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw32|bccwin32/
693
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/
797
694
  lib_dir = "#{@oracle_home}/oci/lib"
798
695
  elsif use_lib32
799
696
  lib_dir = "#{@oracle_home}/lib32"
@@ -812,7 +709,7 @@ class OraConfFC < OraConf
812
709
  print("Get the version of Oracle from SQL*Plus... ")
813
710
  STDOUT.flush
814
711
  version = nil
815
- dev_null = RUBY_PLATFORM =~ /mswin32|mswin64|mingw32|bccwin32/ ? "nul" : "/dev/null"
712
+ dev_null = RUBY_PLATFORM =~ /mswin32|mswin64|mingw/ ? "nul" : "/dev/null"
816
713
  if File.exist?("#{@oracle_home}/bin/plus80.exe")
817
714
  sqlplus = "plus80.exe"
818
715
  else
@@ -837,7 +734,7 @@ class OraConfFC < OraConf
837
734
  version
838
735
  end # get_version
839
736
 
840
- if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw32|bccwin32/ # when Windows
737
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/ # when Windows
841
738
 
842
739
  def is_valid_home?(oracle_home)
843
740
  return false if oracle_home.nil?
@@ -856,11 +753,8 @@ class OraConfFC < OraConf
856
753
  def get_home()
857
754
  oracle_home = ENV['ORACLE_HOME']
858
755
  if oracle_home.nil?
859
- struct = Struct.new("OracleHome", :name, :path)
860
- oracle_homes = []
861
- MiniRegistry.enum_homes do |name, path|
862
- path.chomp!("\\") if path
863
- oracle_homes << struct.new(name, path) if is_valid_home?(path)
756
+ oracle_homes = Registry::oracle_homes.select do |home|
757
+ is_valid_home?(home.path)
864
758
  end
865
759
  if oracle_homes.empty?
866
760
  raise <<EOS
@@ -922,7 +816,7 @@ EOS
922
816
  unless File.exist?("#{@oracle_home}/OCI/INCLUDE/OCI.H")
923
817
  raise "'#{@oracle_home}/OCI/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
924
818
  end
925
- if RUBY_PLATFORM =~ /cygwin|mingw32/
819
+ if RUBY_PLATFORM =~ /cygwin|mingw/
926
820
  " \"-I#{@oracle_home}/OCI/INCLUDE\" -D_int64=\"long long\""
927
821
  else
928
822
  " \"-I#{@oracle_home}/OCI/INCLUDE\""
@@ -1001,56 +895,25 @@ end
1001
895
 
1002
896
  # OraConf for Instant Client
1003
897
  class OraConfIC < OraConf
1004
- def initialize(ic_dir)
898
+ def initialize(inc_dir, lib_dir)
1005
899
  init
1006
900
 
1007
- if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+(?:\.\d+)*)\/client(64)?\/lib(?:64)?/
1008
- # rpm package
1009
- # x86 rpms after 11.1.0.7.0:
1010
- # library: /usr/lib/oracle/X.X/client/lib/
1011
- # include: /usr/include/oracle/X.X/client/
1012
- #
1013
- # x86_64 rpms after 11.1.0.7.0:
1014
- # library: /usr/lib/oracle/X.X/client64/lib/
1015
- # include: /usr/include/oracle/X.X/client64/
1016
- #
1017
- # x86 rpms before 11.1.0.6.0:
1018
- # library: /usr/lib/oracle/X.X.X.X/client/lib/
1019
- # include: /usr/include/oracle/X.X.X.X/client/
1020
- #
1021
- # x86_64 rpms before 11.1.0.6.0:
1022
- # library: /usr/lib/oracle/X.X.X.X/client64/lib/
1023
- # include: /usr/include/oracle/X.X.X.X/client64/
1024
- #
1025
- # third-party x86_64 rpms(*1):
1026
- # library: /usr/lib64/oracle/X.X.X.X/client/lib/
1027
- # or /usr/lib64/oracle/X.X.X.X/client/lib64/
1028
- # include: /usr/include/oracle/X.X.X.X/client/
1029
- #
1030
- # *1 These had been used before Oracle released official x86_64 rpms.
1031
- #
1032
- lib_dir = ic_dir
1033
- inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
1034
- else
1035
- # zip package
1036
- lib_dir = ic_dir
1037
- inc_dir = "#{ic_dir}/sdk/include"
1038
- end
1039
-
1040
- if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw32|bccwin32/ # when Windows
1041
- unless File.exist?("#{ic_dir}/sdk/lib/msvc/oci.lib")
901
+ # check lib_dir
902
+ lib_dirs = lib_dir.split(File::PATH_SEPARATOR)
903
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/ # when Windows
904
+ ocilib = lib_dirs.find do |dir|
905
+ File.exist?("#{dir}/sdk/lib/msvc/oci.lib")
906
+ end
907
+ unless ocilib
1042
908
  raise <<EOS
1043
909
  Could not compile with Oracle instant client.
1044
- #{ic_dir}/sdk/lib/msvc/oci.lib could not be found.
910
+ "sdk/lib/msvc/oci.lib" could not be found in: #{lib_dirs.join(' ')}
911
+ Did you install instantclient-basic?
1045
912
  EOS
1046
- raise 'failed'
1047
913
  end
1048
- @cflags = " \"-I#{inc_dir}\""
1049
- @cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin|mingw32/
1050
- @libs = get_libs("#{ic_dir}/sdk/lib")
914
+ @libs = get_libs("#{ocilib}/sdk/lib")
1051
915
  ld_path = nil
1052
916
  else
1053
- @cflags = " -I#{inc_dir}"
1054
917
  # set ld_path and so_ext
1055
918
  case RUBY_PLATFORM
1056
919
  when /aix/
@@ -1071,34 +934,53 @@ EOS
1071
934
  so_ext = 'so'
1072
935
  end
1073
936
  # check Oracle client library.
1074
- unless File.exist?("#{lib_dir}/libclntsh.#{so_ext}")
1075
- files = Dir.glob("#{lib_dir}/libclntsh.#{so_ext}.*")
937
+ ocilib = lib_dirs.find do |dir|
938
+ File.exist?("#{dir}/libclntsh.#{so_ext}")
939
+ end
940
+ unless ocilib
941
+ files = lib_dirs.map do |dir|
942
+ Dir.glob("#{dir}/libclntsh.#{so_ext}.*")
943
+ end.flatten
1076
944
  if files.empty?
1077
945
  raise <<EOS
1078
946
  Could not compile with Oracle instant client.
1079
- '#{lib_dir}/libclntsh.#{so_ext}' could not be found.
947
+ "libclntsh.#{so_ext}" could not be found in: #{lib_dirs.join(' ')}
1080
948
  Did you install instantclient-basic?
1081
949
  EOS
1082
950
  else
1083
- file = File.basename(files.sort[-1])
951
+ file = files.sort[-1]
1084
952
  raise <<EOS
1085
953
  Could not compile with Oracle instant client.
1086
- #{lib_dir}/libclntsh.#{so_ext} could not be found.
954
+ "libclntsh.#{so_ext}" could not be found in: #{lib_dirs.join(' ')}
1087
955
  You may need to make a symbolic link.
1088
- cd #{lib_dir}
1089
- ln -s #{file} libclntsh.#{so_ext}
956
+ cd #{File.dirname(file)}
957
+ ln -s #{File.basename(file)} libclntsh.#{so_ext}
1090
958
  EOS
1091
959
  end
1092
960
  raise 'failed'
1093
961
  end
1094
962
  @libs = get_libs(lib_dir)
1095
963
  end
1096
- unless File.exist?("#{inc_dir}/oci.h")
964
+
965
+ # check inc_dir
966
+ inc_dirs = inc_dir.split(File::PATH_SEPARATOR)
967
+ ociinc = inc_dirs.find do |dir|
968
+ File.exist?("#{dir}/oci.h")
969
+ end
970
+ unless ociinc
1097
971
  raise <<EOS
1098
- '#{inc_dir}/oci.h' does not exist.
972
+ "oci.h" could not be found in: #{inc_dirs.join(' ')}
1099
973
  Install 'Instant Client SDK'.
1100
974
  EOS
1101
975
  end
976
+ if ociinc.include?(' ')
977
+ @cflags = " \"-I#{ociinc}\""
978
+ else
979
+ @cflags = " -I#{ociinc}"
980
+ end
981
+ @cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin|mingw/
982
+
983
+ # check link
1102
984
  $CFLAGS += @cflags
1103
985
  if try_link_oci()
1104
986
  major = try_constant("OCI_MAJOR_VERSION", "oci.h")
@@ -1108,73 +990,10 @@ EOS
1108
990
  else
1109
991
  # 10.1.0 doesn't have OCI_MAJOR_VERSION and OCI_MINOR_VERSION in oci.h.
1110
992
  @version = "1010"
1111
- if RUBY_PLATFORM =~ /darwin/ and 1.size == 8 and `sw_vers -productVersion`.chomp == "10.7"
1112
- $stderr.print <<EOS
1113
- WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1114
-
1115
- 64-bit Oracle instant client doesn't work on OS X Lion.
1116
- See: https://forums.oracle.com/forums/thread.jspa?threadID=2187558
1117
-
1118
- The compilation is continued because the issue may be fixed in future.
1119
-
1120
- WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1121
- EOS
1122
- end
1123
993
  end
1124
994
  return
1125
995
  end
1126
996
 
1127
- if RUBY_PLATFORM =~ /darwin/
1128
- open('mkmf.log', 'r') do |f|
1129
- while line = f.gets
1130
- if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
1131
- raise <<EOS
1132
- Intel mac instant client is for Mac OS X 10.5.
1133
- It doesn't work on Mac OS X 10.4 or before.
1134
-
1135
- You have three workarounds.
1136
- 1. Compile ruby as ppc binary and use it with ppc instant client.
1137
- 2. Use JRuby and JDBC
1138
- 3. Use a third-party ODBC driver and ruby-odbc.
1139
- EOS
1140
- # '
1141
- end
1142
-
1143
- case line
1144
- when /cputype \(\d+, architecture \w+\) does not match cputype \(\d+\) for specified -arch flag: (\w+)/
1145
- missing_arch = $1
1146
- when /Undefined symbols for architecture (\w+)/
1147
- missing_arch = $1
1148
- when /missing required architecture (\w+) in file/
1149
- missing_arch = $1
1150
- end
1151
-
1152
- if missing_arch
1153
- if [nil].pack('p').size == 8
1154
- my_arch = 'x86_64'
1155
- elsif "\x01\x02".unpack('s')[0] == 0x0201
1156
- my_arch = 'i386'
1157
- else
1158
- my_arch = 'ppc'
1159
- end
1160
- raise <<EOS
1161
- Could not compile with Oracle instant client.
1162
- You may need to set the environment variable RC_ARCHS or ARCHFLAGS as follows:
1163
-
1164
- RC_ARCHS=#{my_arch}
1165
- export RC_ARCHS
1166
- or
1167
- ARCHFLAGS='-arch #{my_arch}'
1168
- export RC_ARCHS
1169
-
1170
- If it does not fix the problem, delete all '-arch #{missing_arch}'
1171
- in '#{RbConfig::CONFIG['archdir']}/rbconfig.rb'.
1172
- EOS
1173
- end
1174
- end
1175
- end
1176
- end
1177
-
1178
997
  unless ld_path.nil?
1179
998
  raise <<EOS
1180
999
  Could not compile with Oracle instant client.