ruby-oci8 2.2.0.2 → 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 (83) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -6
  3. data/ChangeLog +600 -0
  4. data/NEWS +426 -35
  5. data/README.md +27 -9
  6. data/dist-files +13 -2
  7. data/docs/bind-array-to-in_cond.md +38 -0
  8. data/docs/conflicts-local-connections-and-processes.md +98 -0
  9. data/docs/hanging-after-inactivity.md +63 -0
  10. data/docs/install-binary-package.md +15 -11
  11. data/docs/install-full-client.md +18 -21
  12. data/docs/install-instant-client.md +45 -27
  13. data/docs/install-on-osx.md +31 -117
  14. data/docs/ldap-auth-and-function-interposition.md +123 -0
  15. data/docs/number-type-mapping.md +79 -0
  16. data/docs/platform-specific-issues.md +17 -50
  17. data/docs/report-installation-issue.md +11 -8
  18. data/docs/timeout-parameters.md +94 -0
  19. data/ext/oci8/apiwrap.c.tmpl +2 -5
  20. data/ext/oci8/apiwrap.rb +6 -1
  21. data/ext/oci8/apiwrap.yml +39 -143
  22. data/ext/oci8/attr.c +4 -2
  23. data/ext/oci8/bind.c +421 -9
  24. data/ext/oci8/connection_pool.c +3 -3
  25. data/ext/oci8/encoding.c +5 -5
  26. data/ext/oci8/env.c +8 -2
  27. data/ext/oci8/error.c +24 -16
  28. data/ext/oci8/extconf.rb +35 -63
  29. data/ext/oci8/hook_funcs.c +274 -61
  30. data/ext/oci8/lob.c +31 -75
  31. data/ext/oci8/metadata.c +8 -6
  32. data/ext/oci8/object.c +119 -29
  33. data/ext/oci8/oci8.c +46 -133
  34. data/ext/oci8/oci8.h +40 -123
  35. data/ext/oci8/oci8lib.c +178 -46
  36. data/ext/oci8/ocihandle.c +37 -37
  37. data/ext/oci8/ocinumber.c +24 -35
  38. data/ext/oci8/oraconf.rb +168 -337
  39. data/ext/oci8/oradate.c +19 -19
  40. data/ext/oci8/plthook.h +10 -0
  41. data/ext/oci8/plthook_elf.c +433 -268
  42. data/ext/oci8/plthook_osx.c +40 -9
  43. data/ext/oci8/plthook_win32.c +16 -1
  44. data/ext/oci8/stmt.c +52 -17
  45. data/ext/oci8/win32.c +4 -22
  46. data/lib/oci8/bindtype.rb +10 -17
  47. data/lib/oci8/check_load_error.rb +57 -10
  48. data/lib/oci8/compat.rb +5 -1
  49. data/lib/oci8/connection_pool.rb +74 -3
  50. data/lib/oci8/cursor.rb +70 -31
  51. data/lib/oci8/metadata.rb +9 -1
  52. data/lib/oci8/object.rb +14 -1
  53. data/lib/oci8/oci8.rb +184 -58
  54. data/lib/oci8/ocihandle.rb +0 -16
  55. data/lib/oci8/oracle_version.rb +11 -1
  56. data/lib/oci8/properties.rb +55 -0
  57. data/lib/oci8/version.rb +1 -1
  58. data/lib/oci8.rb +48 -4
  59. data/lib/ruby-oci8.rb +1 -0
  60. data/pre-distclean.rb +1 -3
  61. data/ruby-oci8.gemspec +4 -9
  62. data/setup.rb +11 -2
  63. data/test/README.md +37 -0
  64. data/test/config.rb +8 -1
  65. data/test/setup_test_object.sql +42 -14
  66. data/test/setup_test_package.sql +59 -0
  67. data/test/test_all.rb +4 -0
  68. data/test/test_bind_array.rb +70 -0
  69. data/test/test_bind_boolean.rb +99 -0
  70. data/test/test_bind_integer.rb +47 -0
  71. data/test/test_break.rb +11 -9
  72. data/test/test_clob.rb +5 -17
  73. data/test/test_connstr.rb +142 -0
  74. data/test/test_datetime.rb +8 -3
  75. data/test/test_metadata.rb +2 -1
  76. data/test/test_object.rb +99 -18
  77. data/test/test_oci8.rb +170 -46
  78. data/test/test_oranumber.rb +12 -6
  79. data/test/test_package_type.rb +17 -3
  80. data/test/test_properties.rb +17 -0
  81. metadata +45 -55
  82. data/docs/osx-install-dev-tools.png +0 -0
  83. 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|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|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,61 +495,18 @@ 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
- fallback_path = "#{ENV['HOME']}/lib:/usr/local/lib:/lib:/usr/lib"
526
- end
527
- puts " checking DYLD_FALLBACK_LIBRARY_PATH..."
528
- ld_path, file = check_lib_in_path(fallback_path, glob_name, check_proc)
529
498
  if ld_path.nil?
530
- puts " checking OCI_DIR..."
531
- ld_path, file = check_lib_in_path(ENV['OCI_DIR'], glob_name, check_proc)
532
- if ld_path
533
- puts " checking dependent shared libraries in #{file}..."
534
- open("|otool -L #{file}") do |f|
535
- f.gets # discard the first line
536
- while line = f.gets
537
- line =~ /^\s+(\S+)/
538
- libname = $1
539
- case libname
540
- when /^@rpath\/libclntsh\.dylib/, /^@rpath\/libnnz\d\d\.dylib/, /^@loader_path\/libnnz\d\d\.dylib/
541
- # No need to check the real path.
542
- # The current instant client doesn't use @rpath or @loader_path.
543
- when /\/libclntsh\.dylib/, /\/libnnz\d\d.dylib/
544
- raise <<EOS unless File.exists?(libname)
545
- The output of "otool -L #{file}" is:
546
- | #{IO.readlines("|otool -L #{file}").join(' | ')}
547
- Ruby-oci8 doesn't work without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH
548
- because the dependent file "#{libname}" doesn't exist.
549
-
550
- If you need to use ruby-oci8 without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH,
551
- download "fix_oralib.rb" in https://github.com/kubo/fix_oralib_osx
552
- and execute it in the directory "#{File.dirname(file)}" as follows to fix the path.
553
-
554
- cd #{File.dirname(file)}
555
- curl -O https://raw.githubusercontent.com/kubo/fix_oralib_osx/master/fix_oralib.rb
556
- ruby fix_oralib.rb
557
-
558
- Note: DYLD_* environment variables are unavailable for security reasons on OS X 10.11 El Capitan.
559
- EOS
560
- end
561
- end
562
- end
499
+ fallback_path = ENV['DYLD_FALLBACK_LIBRARY_PATH']
500
+ if fallback_path.nil?
501
+ fallback_path = "#{ENV['HOME']}/lib:/usr/local/lib:/lib:/usr/lib"
502
+ puts " checking the default value of DYLD_FALLBACK_LIBRARY_PATH..."
503
+ ld_path, file = check_lib_in_path(fallback_path, glob_name, check_proc)
563
504
  end
564
505
  end
565
506
  if ld_path.nil?
566
507
  raise <<EOS
567
- Set the environment variable DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH or
568
- OCI_DIR to point to the Instant client directory.
569
-
570
- If DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH is set, the environment
571
- variable must be set at runtime also.
572
-
573
- If OCI_DIR is set, dependent shared library paths are checked. If the checking
574
- is passed, ruby-oci8 works without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH.
575
-
576
- Note: OCI_DIR should be absolute path.
577
- 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.
578
510
  EOS
579
511
  end
580
512
  end
@@ -598,8 +530,8 @@ EOS
598
530
  paths.split(File::PATH_SEPARATOR).each do |path|
599
531
  next if path.nil? or path == ''
600
532
  print " checking #{path}... "
601
- path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
602
- 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
603
535
  if files.empty?
604
536
  puts "no"
605
537
  next
@@ -626,7 +558,7 @@ EOS
626
558
  if try_run("int main() { return 0; }")
627
559
  puts "ok"
628
560
  else
629
- puts "ng"
561
+ puts "failed"
630
562
  raise "C compiler doesn't work correctly."
631
563
  end
632
564
  end # check_cc
@@ -672,21 +604,11 @@ EOS
672
604
  STDOUT.flush
673
605
  rubyhdrdir = RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG['archdir']
674
606
  unless File.exist?(rubyhdrdir + '/ruby.h')
675
- puts "ng"
676
- if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{RbConfig::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
677
- raise <<EOS
678
- #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
679
- Run the following commands to fix the problem.
680
-
681
- cd #{RbConfig::CONFIG['archdir']}
682
- sudo ln -s ../universal-darwin8.0/* ./
683
- EOS
684
- else
685
- raise <<EOS
607
+ puts "failed"
608
+ raise <<EOS
686
609
  #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
687
610
  Install the ruby development library.
688
611
  EOS
689
- end
690
612
  end
691
613
  puts "ok"
692
614
  $stdout.flush
@@ -696,23 +618,26 @@ EOS
696
618
  original_libs = $libs
697
619
  begin
698
620
  $libs += " -L#{CONFIG['libdir']} " + @libs
699
- have_func("OCIInitialize", "oci.h")
621
+ have_func("OCIEnvCreate", "oci.h")
700
622
  ensure
701
623
  $libs = original_libs
702
624
  end
703
625
  end
704
626
 
705
- if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
627
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/ # when Windows
706
628
 
707
629
  def get_libs(lib_dir)
708
630
  case RUBY_PLATFORM
709
- when /cygwin|x64-mingw32/
631
+ when /cygwin/
710
632
  regex = ([nil].pack('P').size == 8) ? / T (OCI\w+)/ : / T _(OCI\w+)/
633
+ oci_funcs = YAML.load(open(File.dirname(__FILE__) + '/apiwrap.yml')).keys.collect do |func|
634
+ func =~ /_nb$/ ? $` : func
635
+ end
711
636
  open("OCI.def", "w") do |f|
712
637
  f.puts("EXPORTS")
713
638
  open("|nm #{lib_dir}/MSVC/OCI.LIB") do |r|
714
639
  while line = r.gets
715
- f.puts($1) if regex =~ line
640
+ f.puts($1) if regex =~ line and oci_funcs.include?($1)
716
641
  end
717
642
  end
718
643
  end
@@ -722,22 +647,6 @@ EOS
722
647
  system(command)
723
648
  puts("done")
724
649
  "-L. -lOCI"
725
- when /bccwin32/
726
- # replace '/' to '\\' because bcc linker misunderstands
727
- # 'C:/foo/bar/OCI.LIB' as unknown option.
728
- lib = "#{lib_dir}/BORLAND/OCI.LIB"
729
- return lib.tr('/', '\\') if File.exist?(lib)
730
- raise <<EOS
731
- #{lib} does not exist.
732
-
733
- Your Oracle may not support Borland C++.
734
- If you want to run this module, run the following command at your own risk.
735
- cd #{lib_dir.tr('/', '\\')}
736
- mkdir Borland
737
- cd Borland
738
- coff2omf ..\\MSVC\\OCI.LIB OCI.LIB
739
- EOS
740
- exit 1
741
650
  else
742
651
  "\"#{lib_dir}/MSVC/OCI.LIB\""
743
652
  end
@@ -781,7 +690,7 @@ class OraConfFC < OraConf
781
690
  use_lib32 = false
782
691
  end
783
692
 
784
- if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
693
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/
785
694
  lib_dir = "#{@oracle_home}/oci/lib"
786
695
  elsif use_lib32
787
696
  lib_dir = "#{@oracle_home}/lib32"
@@ -800,7 +709,7 @@ class OraConfFC < OraConf
800
709
  print("Get the version of Oracle from SQL*Plus... ")
801
710
  STDOUT.flush
802
711
  version = nil
803
- dev_null = RUBY_PLATFORM =~ /mswin32|mingw32|bccwin32/ ? "nul" : "/dev/null"
712
+ dev_null = RUBY_PLATFORM =~ /mswin32|mswin64|mingw/ ? "nul" : "/dev/null"
804
713
  if File.exist?("#{@oracle_home}/bin/plus80.exe")
805
714
  sqlplus = "plus80.exe"
806
715
  else
@@ -825,7 +734,7 @@ class OraConfFC < OraConf
825
734
  version
826
735
  end # get_version
827
736
 
828
- if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
737
+ if RUBY_PLATFORM =~ /mswin32|mswin64|cygwin|mingw/ # when Windows
829
738
 
830
739
  def is_valid_home?(oracle_home)
831
740
  return false if oracle_home.nil?
@@ -844,11 +753,8 @@ class OraConfFC < OraConf
844
753
  def get_home()
845
754
  oracle_home = ENV['ORACLE_HOME']
846
755
  if oracle_home.nil?
847
- struct = Struct.new("OracleHome", :name, :path)
848
- oracle_homes = []
849
- MiniRegistry.enum_homes do |name, path|
850
- path.chomp!("\\") if path
851
- 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)
852
758
  end
853
759
  if oracle_homes.empty?
854
760
  raise <<EOS
@@ -910,7 +816,7 @@ EOS
910
816
  unless File.exist?("#{@oracle_home}/OCI/INCLUDE/OCI.H")
911
817
  raise "'#{@oracle_home}/OCI/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
912
818
  end
913
- if RUBY_PLATFORM =~ /cygwin|mingw32/
819
+ if RUBY_PLATFORM =~ /cygwin|mingw/
914
820
  " \"-I#{@oracle_home}/OCI/INCLUDE\" -D_int64=\"long long\""
915
821
  else
916
822
  " \"-I#{@oracle_home}/OCI/INCLUDE\""
@@ -989,56 +895,25 @@ end
989
895
 
990
896
  # OraConf for Instant Client
991
897
  class OraConfIC < OraConf
992
- def initialize(ic_dir)
898
+ def initialize(inc_dir, lib_dir)
993
899
  init
994
900
 
995
- if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+(?:\.\d+)*)\/client(64)?\/lib(?:64)?/
996
- # rpm package
997
- # x86 rpms after 11.1.0.7.0:
998
- # library: /usr/lib/oracle/X.X/client/lib/
999
- # include: /usr/include/oracle/X.X/client/
1000
- #
1001
- # x86_64 rpms after 11.1.0.7.0:
1002
- # library: /usr/lib/oracle/X.X/client64/lib/
1003
- # include: /usr/include/oracle/X.X/client64/
1004
- #
1005
- # x86 rpms before 11.1.0.6.0:
1006
- # library: /usr/lib/oracle/X.X.X.X/client/lib/
1007
- # include: /usr/include/oracle/X.X.X.X/client/
1008
- #
1009
- # x86_64 rpms before 11.1.0.6.0:
1010
- # library: /usr/lib/oracle/X.X.X.X/client64/lib/
1011
- # include: /usr/include/oracle/X.X.X.X/client64/
1012
- #
1013
- # third-party x86_64 rpms(*1):
1014
- # library: /usr/lib64/oracle/X.X.X.X/client/lib/
1015
- # or /usr/lib64/oracle/X.X.X.X/client/lib64/
1016
- # include: /usr/include/oracle/X.X.X.X/client/
1017
- #
1018
- # *1 These had been used before Oracle released official x86_64 rpms.
1019
- #
1020
- lib_dir = ic_dir
1021
- inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
1022
- else
1023
- # zip package
1024
- lib_dir = ic_dir
1025
- inc_dir = "#{ic_dir}/sdk/include"
1026
- end
1027
-
1028
- if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
1029
- 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
1030
908
  raise <<EOS
1031
909
  Could not compile with Oracle instant client.
1032
- #{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?
1033
912
  EOS
1034
- raise 'failed'
1035
913
  end
1036
- @cflags = " \"-I#{inc_dir}\""
1037
- @cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin|mingw32/
1038
- @libs = get_libs("#{ic_dir}/sdk/lib")
914
+ @libs = get_libs("#{ocilib}/sdk/lib")
1039
915
  ld_path = nil
1040
916
  else
1041
- @cflags = " -I#{inc_dir}"
1042
917
  # set ld_path and so_ext
1043
918
  case RUBY_PLATFORM
1044
919
  when /aix/
@@ -1059,34 +934,53 @@ EOS
1059
934
  so_ext = 'so'
1060
935
  end
1061
936
  # check Oracle client library.
1062
- unless File.exist?("#{lib_dir}/libclntsh.#{so_ext}")
1063
- 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
1064
944
  if files.empty?
1065
945
  raise <<EOS
1066
946
  Could not compile with Oracle instant client.
1067
- '#{lib_dir}/libclntsh.#{so_ext}' could not be found.
947
+ "libclntsh.#{so_ext}" could not be found in: #{lib_dirs.join(' ')}
1068
948
  Did you install instantclient-basic?
1069
949
  EOS
1070
950
  else
1071
- file = File.basename(files.sort[-1])
951
+ file = files.sort[-1]
1072
952
  raise <<EOS
1073
953
  Could not compile with Oracle instant client.
1074
- #{lib_dir}/libclntsh.#{so_ext} could not be found.
954
+ "libclntsh.#{so_ext}" could not be found in: #{lib_dirs.join(' ')}
1075
955
  You may need to make a symbolic link.
1076
- cd #{lib_dir}
1077
- ln -s #{file} libclntsh.#{so_ext}
956
+ cd #{File.dirname(file)}
957
+ ln -s #{File.basename(file)} libclntsh.#{so_ext}
1078
958
  EOS
1079
959
  end
1080
960
  raise 'failed'
1081
961
  end
1082
962
  @libs = get_libs(lib_dir)
1083
963
  end
1084
- 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
1085
971
  raise <<EOS
1086
- '#{inc_dir}/oci.h' does not exist.
972
+ "oci.h" could not be found in: #{inc_dirs.join(' ')}
1087
973
  Install 'Instant Client SDK'.
1088
974
  EOS
1089
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
1090
984
  $CFLAGS += @cflags
1091
985
  if try_link_oci()
1092
986
  major = try_constant("OCI_MAJOR_VERSION", "oci.h")
@@ -1096,73 +990,10 @@ EOS
1096
990
  else
1097
991
  # 10.1.0 doesn't have OCI_MAJOR_VERSION and OCI_MINOR_VERSION in oci.h.
1098
992
  @version = "1010"
1099
- if RUBY_PLATFORM =~ /darwin/ and 1.size == 8 and `sw_vers -productVersion`.chomp == "10.7"
1100
- $stderr.print <<EOS
1101
- WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1102
-
1103
- 64-bit Oracle instant client doesn't work on OS X Lion.
1104
- See: https://forums.oracle.com/forums/thread.jspa?threadID=2187558
1105
-
1106
- The compilation is continued because the issue may be fixed in future.
1107
-
1108
- WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1109
- EOS
1110
- end
1111
993
  end
1112
994
  return
1113
995
  end
1114
996
 
1115
- if RUBY_PLATFORM =~ /darwin/
1116
- open('mkmf.log', 'r') do |f|
1117
- while line = f.gets
1118
- if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
1119
- raise <<EOS
1120
- Intel mac instant client is for Mac OS X 10.5.
1121
- It doesn't work on Mac OS X 10.4 or before.
1122
-
1123
- You have three workarounds.
1124
- 1. Compile ruby as ppc binary and use it with ppc instant client.
1125
- 2. Use JRuby and JDBC
1126
- 3. Use a third-party ODBC driver and ruby-odbc.
1127
- EOS
1128
- # '
1129
- end
1130
-
1131
- case line
1132
- when /cputype \(\d+, architecture \w+\) does not match cputype \(\d+\) for specified -arch flag: (\w+)/
1133
- missing_arch = $1
1134
- when /Undefined symbols for architecture (\w+)/
1135
- missing_arch = $1
1136
- when /missing required architecture (\w+) in file/
1137
- missing_arch = $1
1138
- end
1139
-
1140
- if missing_arch
1141
- if [nil].pack('p').size == 8
1142
- my_arch = 'x86_64'
1143
- elsif "\x01\x02".unpack('s')[0] == 0x0201
1144
- my_arch = 'i386'
1145
- else
1146
- my_arch = 'ppc'
1147
- end
1148
- raise <<EOS
1149
- Could not compile with Oracle instant client.
1150
- You may need to set the environment variable RC_ARCHS or ARCHFLAGS as follows:
1151
-
1152
- RC_ARCHS=#{my_arch}
1153
- export RC_ARCHS
1154
- or
1155
- ARCHFLAGS='-arch #{my_arch}'
1156
- export RC_ARCHS
1157
-
1158
- If it does not fix the problem, delete all '-arch #{missing_arch}'
1159
- in '#{RbConfig::CONFIG['archdir']}/rbconfig.rb'.
1160
- EOS
1161
- end
1162
- end
1163
- end
1164
- end
1165
-
1166
997
  unless ld_path.nil?
1167
998
  raise <<EOS
1168
999
  Could not compile with Oracle instant client.