ruby-oci8-master 2.0.7
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 +2321 -0
- data/Makefile +88 -0
- data/NEWS +303 -0
- data/README +76 -0
- data/VERSION +1 -0
- data/dist-files +83 -0
- data/doc/api.en.html +527 -0
- data/doc/api.en.rd +554 -0
- data/doc/api.ja.html +525 -0
- data/doc/api.ja.rd +557 -0
- data/doc/manual.css +35 -0
- data/ext/oci8/.document +18 -0
- data/ext/oci8/MANIFEST +18 -0
- data/ext/oci8/apiwrap.c.tmpl +182 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1455 -0
- data/ext/oci8/attr.c +105 -0
- data/ext/oci8/bind.c +366 -0
- data/ext/oci8/connection_pool.c +199 -0
- data/ext/oci8/encoding.c +289 -0
- data/ext/oci8/env.c +178 -0
- data/ext/oci8/error.c +378 -0
- data/ext/oci8/extconf.rb +179 -0
- data/ext/oci8/lob.c +805 -0
- data/ext/oci8/metadata.c +232 -0
- data/ext/oci8/object.c +727 -0
- data/ext/oci8/oci8.c +1156 -0
- data/ext/oci8/oci8.h +574 -0
- data/ext/oci8/oci8lib.c +527 -0
- data/ext/oci8/ocidatetime.c +484 -0
- data/ext/oci8/ocihandle.c +751 -0
- data/ext/oci8/ocinumber.c +1612 -0
- data/ext/oci8/oraconf.rb +1119 -0
- data/ext/oci8/oradate.c +611 -0
- data/ext/oci8/oranumber_util.c +352 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/stmt.c +673 -0
- data/ext/oci8/thread_util.c +85 -0
- data/ext/oci8/thread_util.h +30 -0
- data/ext/oci8/win32.c +137 -0
- data/lib/.document +1 -0
- data/lib/dbd/OCI8.rb +591 -0
- data/lib/oci8.rb.in +94 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +349 -0
- data/lib/oci8/compat.rb +113 -0
- data/lib/oci8/connection_pool.rb +99 -0
- data/lib/oci8/datetime.rb +611 -0
- data/lib/oci8/encoding-init.rb +74 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2132 -0
- data/lib/oci8/object.rb +581 -0
- data/lib/oci8/oci8.rb +721 -0
- data/lib/oci8/ocihandle.rb +425 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/lib/oci8/properties.rb +73 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +63 -0
- data/setup.rb +1331 -0
- data/test/README +4 -0
- data/test/config.rb +122 -0
- data/test/test_all.rb +51 -0
- data/test/test_appinfo.rb +63 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +46 -0
- data/test/test_bind_time.rb +178 -0
- data/test/test_break.rb +96 -0
- data/test/test_clob.rb +82 -0
- data/test/test_connstr.rb +81 -0
- data/test/test_datetime.rb +582 -0
- data/test/test_dbi.rb +366 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +100 -0
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1399 -0
- data/test/test_oci8.rb +434 -0
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +256 -0
- data/test/test_oranumber.rb +746 -0
- data/test/test_rowid.rb +33 -0
- metadata +137 -0
data/ext/oci8/oraconf.rb
ADDED
@@ -0,0 +1,1119 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
# compatibility for ruby-1.9
|
4
|
+
RbConfig = Config unless defined? RbConfig
|
5
|
+
|
6
|
+
module MiniRegistry
|
7
|
+
class MiniRegistryError < StandardError
|
8
|
+
attr_reader :api_name
|
9
|
+
attr_reader :code
|
10
|
+
def initialize(api_name, code)
|
11
|
+
@api_name = api_name
|
12
|
+
@code = code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
|
16
|
+
# Windows
|
17
|
+
require 'Win32API' # raise LoadError when UNIX.
|
18
|
+
|
19
|
+
# I looked in Win32Module by MoonWolf <URL:http://www.moonwolf.com/ruby/>,
|
20
|
+
# copy the minimum code and reorganize it.
|
21
|
+
ERROR_SUCCESS = 0
|
22
|
+
ERROR_FILE_NOT_FOUND = 2
|
23
|
+
ERROR_NO_MORE_ITEMS = 259
|
24
|
+
|
25
|
+
HKEY_LOCAL_MACHINE = 0x80000002
|
26
|
+
KEY_ENUMERATE_SUB_KEYS = 0x0008
|
27
|
+
KEY_QUERY_VALUE = 0x0001
|
28
|
+
RegOpenKeyExA = Win32API.new('advapi32', 'RegOpenKeyExA', 'LPLLP', 'L')
|
29
|
+
RegEnumKeyExA = Win32API.new('advapi32', 'RegEnumKeyExA', 'LLPPPPPP', 'L')
|
30
|
+
RegQueryValueExA = Win32API.new('advapi32','RegQueryValueExA','LPPPPP','L')
|
31
|
+
RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
|
32
|
+
|
33
|
+
def self.get_str_value(hKey, name)
|
34
|
+
lpcbData = [0].pack('L')
|
35
|
+
code = RegQueryValueExA.call(hKey, name, nil, nil, nil, lpcbData)
|
36
|
+
if code == ERROR_FILE_NOT_FOUND
|
37
|
+
return nil
|
38
|
+
elsif code != ERROR_SUCCESS
|
39
|
+
raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
|
40
|
+
end
|
41
|
+
len = lpcbData.unpack('L')[0]
|
42
|
+
lpType = [0].pack('L')
|
43
|
+
lpData = "\0"*len
|
44
|
+
lpcbData = [len].pack('L')
|
45
|
+
code = RegQueryValueExA.call(hKey, name, nil, lpType, lpData, lpcbData)
|
46
|
+
if code != ERROR_SUCCESS
|
47
|
+
raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
|
48
|
+
end
|
49
|
+
lpData.unpack('Z*')[0]
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.enum_homes
|
53
|
+
phkResult = [0].pack('L')
|
54
|
+
code = RegOpenKeyExA.call(HKEY_LOCAL_MACHINE, 'SOFTWARE\ORACLE', 0, 0x20019, phkResult)
|
55
|
+
if code != ERROR_SUCCESS
|
56
|
+
raise MiniRegistryError.new("Win32::RegOpenKeyExA", code)
|
57
|
+
end
|
58
|
+
hKey = phkResult.unpack('L')[0]
|
59
|
+
idx = 0
|
60
|
+
maxkeylen = 256
|
61
|
+
loop do
|
62
|
+
lpName = "\0" * maxkeylen
|
63
|
+
lpcName = [maxkeylen].pack('L')
|
64
|
+
code = RegEnumKeyExA.call(hKey, idx, lpName, lpcName, nil, nil, nil, nil);
|
65
|
+
break if code == ERROR_NO_MORE_ITEMS
|
66
|
+
if code != ERROR_SUCCESS
|
67
|
+
RegCloseKey.call(hKey)
|
68
|
+
raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
|
69
|
+
end
|
70
|
+
code = RegOpenKeyExA.call(hKey, lpName, 0, KEY_QUERY_VALUE, phkResult)
|
71
|
+
if code != ERROR_SUCCESS
|
72
|
+
RegCloseKey.call(hKey)
|
73
|
+
raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
|
74
|
+
end
|
75
|
+
hSubkey = phkResult.unpack('L')[0]
|
76
|
+
|
77
|
+
name = get_str_value(hSubkey, 'ORACLE_HOME_NAME')
|
78
|
+
path = get_str_value(hSubkey, 'ORACLE_HOME')
|
79
|
+
yield name, path
|
80
|
+
RegCloseKey.call(hSubkey)
|
81
|
+
idx += 1
|
82
|
+
end
|
83
|
+
RegCloseKey.call(hKey)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end # module MiniRegistry
|
88
|
+
|
89
|
+
# minimal implementation to read information of a shared object.
|
90
|
+
class MiniSOReader
|
91
|
+
attr_reader :file_format
|
92
|
+
attr_reader :cpu
|
93
|
+
attr_reader :endian
|
94
|
+
attr_reader :bits
|
95
|
+
|
96
|
+
def initialize(filename)
|
97
|
+
f = open(filename, 'rb')
|
98
|
+
begin
|
99
|
+
case file_header = f.read(2)
|
100
|
+
when "\177E"
|
101
|
+
# Linux, Solaris and HP-UX(64-bit)
|
102
|
+
read_elf(f) if f.read(2) == 'LF'
|
103
|
+
when "MZ"
|
104
|
+
# Windows
|
105
|
+
read_pe(f)
|
106
|
+
when "\x02\x10"
|
107
|
+
# HP-UX PA-RISC1.1
|
108
|
+
read_parisc(f)
|
109
|
+
when "\xfe\xed"
|
110
|
+
# Big-endian Mach-O File
|
111
|
+
read_mach_o_be(f)
|
112
|
+
when "\xce\xfa"
|
113
|
+
# 32-bit Little-endian Mach-O File
|
114
|
+
read_mach_o_le(f, 32)
|
115
|
+
when "\xcf\xfa"
|
116
|
+
# 64-bit Little-endian Mach-O File
|
117
|
+
read_mach_o_le(f, 64)
|
118
|
+
when "\xca\xfe"
|
119
|
+
# Universal binary
|
120
|
+
read_mach_o_unversal(f)
|
121
|
+
else
|
122
|
+
# AIX and Tru64
|
123
|
+
raise format("unknown file header: %02x %02x", file_header[0].to_i, file_header[1].to_i)
|
124
|
+
end
|
125
|
+
ensure
|
126
|
+
f.close
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
# ELF format
|
132
|
+
def read_elf(f)
|
133
|
+
# 0-3 "\177ELF"
|
134
|
+
@file_format = :elf
|
135
|
+
# 4
|
136
|
+
case f.read(1).unpack('C')[0]
|
137
|
+
when 1
|
138
|
+
@bits = 32
|
139
|
+
when 2
|
140
|
+
@bits = 64
|
141
|
+
else
|
142
|
+
raise 'Invalid ELF class'
|
143
|
+
end
|
144
|
+
# 5
|
145
|
+
case f.read(1).unpack('C')[0]
|
146
|
+
when 1
|
147
|
+
@endian = :little
|
148
|
+
pack_type_short = 'v'
|
149
|
+
when 2
|
150
|
+
@endian = :big
|
151
|
+
pack_type_short = 'n'
|
152
|
+
else
|
153
|
+
raise 'Invalid ELF byte order'
|
154
|
+
end
|
155
|
+
# 6
|
156
|
+
raise 'Invalid ELF header version' if f.read(1) != "\x01"
|
157
|
+
# 16-17
|
158
|
+
f.seek(16, IO::SEEK_SET)
|
159
|
+
raise 'Invalid ELF filetype' if f.read(2).unpack(pack_type_short)[0] != 3
|
160
|
+
# 18-19
|
161
|
+
case archtype = f.read(2).unpack(pack_type_short)[0]
|
162
|
+
when 2
|
163
|
+
@cpu = :sparc
|
164
|
+
when 3
|
165
|
+
@cpu = :i386
|
166
|
+
when 15
|
167
|
+
@cpu = :parisc
|
168
|
+
when 18
|
169
|
+
@cpu = :sparc32plus
|
170
|
+
when 20
|
171
|
+
@cpu = :ppc
|
172
|
+
when 21
|
173
|
+
@cpu = :ppc64
|
174
|
+
when 22
|
175
|
+
@cpu = :s390
|
176
|
+
when 43
|
177
|
+
@cpu = :sparcv9
|
178
|
+
when 50
|
179
|
+
@cpu = :ia64
|
180
|
+
when 62
|
181
|
+
@cpu = :x86_64
|
182
|
+
else
|
183
|
+
raise "Invalid ELF archtype: #{archtype}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# PE/COFF format
|
188
|
+
def read_pe(f)
|
189
|
+
# 0-1 "MZ"
|
190
|
+
@file_format = :pe
|
191
|
+
# 60-63
|
192
|
+
f.seek(60, IO::SEEK_SET)
|
193
|
+
pe_offset = f.read(4).unpack('V')[0]
|
194
|
+
# read PE signature
|
195
|
+
f.seek(pe_offset)
|
196
|
+
raise 'invalid pe format' if f.read(4) != "PE\000\000"
|
197
|
+
# read COFF header
|
198
|
+
case machine = f.read(2).unpack('v')[0]
|
199
|
+
when 0x014c
|
200
|
+
@cpu = :i386
|
201
|
+
@endian = :little
|
202
|
+
@bits = 32
|
203
|
+
when 0x0200
|
204
|
+
@cpu = :ia64
|
205
|
+
@endian = :little
|
206
|
+
@bits = 64
|
207
|
+
when 0x8664
|
208
|
+
@cpu = :x86_64
|
209
|
+
@endian = :little
|
210
|
+
@bits = 64
|
211
|
+
else
|
212
|
+
raise "Invalid coff machine: #{machine}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# HP-UX PA-RISC(32 bit)
|
217
|
+
def read_parisc(f)
|
218
|
+
# 0-1 system_id - CPU_PA_RISC1_1
|
219
|
+
@file_format = :pa_risc
|
220
|
+
# 2-3 a_magic - SHL_MAGIC
|
221
|
+
raise 'invalid a_magic' if f.read(2).unpack('n')[0] != 0x10e
|
222
|
+
@bits = 32
|
223
|
+
@endian = :big
|
224
|
+
@cpu = :parisc
|
225
|
+
end
|
226
|
+
|
227
|
+
# Big-endian Mach-O File
|
228
|
+
def read_mach_o_be(f)
|
229
|
+
@file_format = :mach_o
|
230
|
+
@endian = :big
|
231
|
+
case f.read(2)
|
232
|
+
when "\xfa\xce" # feedface
|
233
|
+
@cpu = :ppc
|
234
|
+
@bits = 32
|
235
|
+
when "\xfa\xcf" # feedfacf
|
236
|
+
@cpu = :ppc64
|
237
|
+
@bits = 64
|
238
|
+
else
|
239
|
+
raise "unknown file format"
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def read_mach_o_le(f, bits)
|
244
|
+
@file_format = :mach_o
|
245
|
+
@endian = :little
|
246
|
+
raise 'unknown file format' if f.read(2) != "\xed\xfe"
|
247
|
+
case bits
|
248
|
+
when 32
|
249
|
+
@cpu = :i386
|
250
|
+
@bits = 32
|
251
|
+
when 64
|
252
|
+
@cpu = :x86_64
|
253
|
+
@bits = 64
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def read_mach_o_unversal(f)
|
258
|
+
raise 'unknown file format' if f.read(2) != "\xba\xbe" # cafebabe
|
259
|
+
@file_format = :universal
|
260
|
+
nfat_arch = f.read(4).unpack('N')[0]
|
261
|
+
@cpu = []
|
262
|
+
@endian = []
|
263
|
+
@bits = []
|
264
|
+
nfat_arch.times do
|
265
|
+
case cputype = f.read(4).unpack('N')[0]
|
266
|
+
when 7
|
267
|
+
@cpu << :i386
|
268
|
+
@endian << :little
|
269
|
+
@bits << 32
|
270
|
+
when 7 + 0x01000000
|
271
|
+
@cpu << :x86_64
|
272
|
+
@endian << :little
|
273
|
+
@bits << 64
|
274
|
+
when 18
|
275
|
+
@cpu << :ppc
|
276
|
+
@endian << :big
|
277
|
+
@bits << 32
|
278
|
+
when 18 + 0x01000000
|
279
|
+
@cpu << :ppc64
|
280
|
+
@endian << :big
|
281
|
+
@bits << 64
|
282
|
+
else
|
283
|
+
raise "Unknown mach-o cputype: #{cputype}"
|
284
|
+
end
|
285
|
+
f.seek(4 * 4, IO::SEEK_CUR)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
|
290
|
+
class OraConf
|
291
|
+
attr_reader :cc_is_gcc
|
292
|
+
attr_reader :version
|
293
|
+
attr_reader :cflags
|
294
|
+
attr_reader :libs
|
295
|
+
|
296
|
+
def initialize
|
297
|
+
raise 'use OraConf.get instead'
|
298
|
+
end
|
299
|
+
|
300
|
+
def self.get
|
301
|
+
original_CFLAGS = $CFLAGS
|
302
|
+
original_defs = $defs
|
303
|
+
ic_dir = nil
|
304
|
+
begin
|
305
|
+
# check Oracle instant client
|
306
|
+
if with_config('instant-client')
|
307
|
+
puts <<EOS
|
308
|
+
=======================================================
|
309
|
+
|
310
|
+
'--with-instant-client' is an obsolete option. ignore it.
|
311
|
+
|
312
|
+
=======================================================
|
313
|
+
EOS
|
314
|
+
end
|
315
|
+
ic_dir = check_ic_dir
|
316
|
+
if ic_dir
|
317
|
+
OraConfIC.new(ic_dir)
|
318
|
+
else
|
319
|
+
OraConfFC.new()
|
320
|
+
end
|
321
|
+
rescue
|
322
|
+
case ENV['LANG']
|
323
|
+
when /^ja/
|
324
|
+
lang = 'ja'
|
325
|
+
else
|
326
|
+
lang = 'en'
|
327
|
+
end
|
328
|
+
print <<EOS
|
329
|
+
---------------------------------------------------
|
330
|
+
Error Message:
|
331
|
+
#{$!.to_s.gsub(/\n/, "\n ")}
|
332
|
+
Backtrace:
|
333
|
+
#{$!.backtrace.join("\n ")}
|
334
|
+
---------------------------------------------------
|
335
|
+
See:
|
336
|
+
* http://ruby-oci8.rubyforge.org/#{lang}/HowToInstall.html
|
337
|
+
* http://ruby-oci8.rubyforge.org/#{lang}/ReportInstallProblem.html
|
338
|
+
|
339
|
+
EOS
|
340
|
+
exc = RuntimeError.new
|
341
|
+
exc.set_backtrace($!.backtrace)
|
342
|
+
raise exc
|
343
|
+
ensure
|
344
|
+
$CFLAGS = original_CFLAGS
|
345
|
+
$defs = original_defs
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
def self.ld_envs
|
350
|
+
@@ld_envs
|
351
|
+
end
|
352
|
+
|
353
|
+
private
|
354
|
+
|
355
|
+
def self.make_proc_to_check_cpu(*expect)
|
356
|
+
Proc.new do |file|
|
357
|
+
so = MiniSOReader.new(file)
|
358
|
+
if expect.include? so.cpu
|
359
|
+
true
|
360
|
+
else
|
361
|
+
puts " skip: #{file} is for #{so.cpu} cpu."
|
362
|
+
false
|
363
|
+
end
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def self.check_ic_dir
|
368
|
+
puts "checking for load library path... "
|
369
|
+
STDOUT.flush
|
370
|
+
|
371
|
+
# get library load path names
|
372
|
+
oci_basename = 'libclntsh'
|
373
|
+
oci_glob_postfix = '.[0-9]*'
|
374
|
+
nls_data_basename = ['libociei', 'libociicus']
|
375
|
+
@@ld_envs = %w[LD_LIBRARY_PATH]
|
376
|
+
so_ext = 'so'
|
377
|
+
nls_data_ext = nil
|
378
|
+
check_proc = nil
|
379
|
+
size_of_pointer = begin
|
380
|
+
# the size of a pointer.
|
381
|
+
[nil].pack('P').size
|
382
|
+
rescue ArgumentError
|
383
|
+
# Rubinius 1.2.3 doesn't support Array#pack('P').
|
384
|
+
# Use Fixnum#size, which returns the size of long.
|
385
|
+
1.size
|
386
|
+
end
|
387
|
+
is_32bit = size_of_pointer == 4
|
388
|
+
is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102
|
389
|
+
case RUBY_PLATFORM
|
390
|
+
when /mswin32|cygwin|mingw32|bccwin32/
|
391
|
+
oci_basename = 'oci'
|
392
|
+
oci_glob_postfix = ''
|
393
|
+
nls_data_basename = ['oraociei11', 'oraociicus11', 'oraociei10', 'oraociicus10']
|
394
|
+
@@ld_envs = %w[PATH]
|
395
|
+
so_ext = 'dll'
|
396
|
+
when /i.86-linux/
|
397
|
+
check_proc = make_proc_to_check_cpu(:i386)
|
398
|
+
when /ia64-linux/
|
399
|
+
check_proc = make_proc_to_check_cpu(:ia64)
|
400
|
+
when /x86_64-linux/
|
401
|
+
# RUBY_PLATFORM depends on the compilation environment.
|
402
|
+
# Even though it is x86_64-linux, the compiled ruby may
|
403
|
+
# be a 32-bit executable.
|
404
|
+
check_proc = make_proc_to_check_cpu(is_32bit ? :i386 : :x86_64)
|
405
|
+
when /solaris/
|
406
|
+
if is_32bit
|
407
|
+
@@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH]
|
408
|
+
if is_big_endian
|
409
|
+
check_proc = make_proc_to_check_cpu(:sparc, :sparc32plus)
|
410
|
+
else
|
411
|
+
check_proc = make_proc_to_check_cpu(:i386)
|
412
|
+
end
|
413
|
+
else
|
414
|
+
@@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH]
|
415
|
+
if is_big_endian
|
416
|
+
check_proc = make_proc_to_check_cpu(:sparcv9)
|
417
|
+
else
|
418
|
+
check_proc = make_proc_to_check_cpu(:x86_64)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
when /aix/
|
422
|
+
oci_glob_postfix = ''
|
423
|
+
@@ld_envs = %w[LIBPATH]
|
424
|
+
so_ext = 'a'
|
425
|
+
nls_data_ext = 'so'
|
426
|
+
when /hppa.*-hpux/
|
427
|
+
if is_32bit
|
428
|
+
@@ld_envs = %w[SHLIB_PATH]
|
429
|
+
end
|
430
|
+
so_ext = 'sl'
|
431
|
+
when /darwin/
|
432
|
+
@@ld_envs = %w[DYLD_LIBRARY_PATH]
|
433
|
+
so_ext = 'dylib'
|
434
|
+
if is_32bit
|
435
|
+
if is_big_endian
|
436
|
+
this_cpu = :ppc # 32-bit big-endian
|
437
|
+
else
|
438
|
+
this_cpu = :i386 # 32-bit little-endian
|
439
|
+
end
|
440
|
+
else
|
441
|
+
if is_big_endian
|
442
|
+
this_cpu = :ppc64 # 64-bit big-endian
|
443
|
+
else
|
444
|
+
this_cpu = :x86_64 # 64-bit little-endian
|
445
|
+
end
|
446
|
+
end
|
447
|
+
check_proc = Proc.new do |file|
|
448
|
+
so = MiniSOReader.new(file)
|
449
|
+
if so.file_format == :universal
|
450
|
+
if so.cpu.include? this_cpu
|
451
|
+
true
|
452
|
+
else
|
453
|
+
if so.cpu.size > 1
|
454
|
+
arch_types = so.cpu[0..-2].join(', ') + ' and ' + so.cpu[-1].to_s
|
455
|
+
else
|
456
|
+
arch_types = so.cpu[0]
|
457
|
+
end
|
458
|
+
puts " skip: #{file} is for #{arch_types} cpu."
|
459
|
+
false
|
460
|
+
end
|
461
|
+
else
|
462
|
+
if so.cpu == this_cpu
|
463
|
+
true
|
464
|
+
else
|
465
|
+
puts " skip: #{file} is for #{so.cpu} cpu."
|
466
|
+
false
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
glob_name = "#{oci_basename}.#{so_ext}#{oci_glob_postfix}"
|
473
|
+
ld_path = nil
|
474
|
+
file = nil
|
475
|
+
@@ld_envs.each do |env|
|
476
|
+
if ENV[env].nil?
|
477
|
+
puts " #{env} is not set."
|
478
|
+
next
|
479
|
+
end
|
480
|
+
puts " #{env}... "
|
481
|
+
ld_path, file = check_lib_in_path(ENV[env], glob_name, check_proc)
|
482
|
+
break if ld_path
|
483
|
+
end
|
484
|
+
|
485
|
+
if ld_path.nil?
|
486
|
+
case RUBY_PLATFORM
|
487
|
+
when /linux/
|
488
|
+
open("|/sbin/ldconfig -p") do |f|
|
489
|
+
print " checking ld.so.conf... "
|
490
|
+
STDOUT.flush
|
491
|
+
while line = f.gets
|
492
|
+
if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/
|
493
|
+
file = "#$1/libclntsh.so.#$2"
|
494
|
+
path = $1
|
495
|
+
next if (check_proc && !check_proc.call(file))
|
496
|
+
ld_path = path
|
497
|
+
puts "yes"
|
498
|
+
break
|
499
|
+
end
|
500
|
+
end
|
501
|
+
puts "no"
|
502
|
+
end
|
503
|
+
when /solaris/
|
504
|
+
if is_32bit
|
505
|
+
crle_cmd = 'crle'
|
506
|
+
else
|
507
|
+
crle_cmd = 'crle -64'
|
508
|
+
end
|
509
|
+
open('|env LANG=C /usr/bin/' + crle_cmd) do |f|
|
510
|
+
while line = f.gets
|
511
|
+
if line =~ /Default Library Path[^:]*:\s*(\S*)/
|
512
|
+
puts " checking output of `#{crle_cmd}'... "
|
513
|
+
ld_path, file = check_lib_in_path($1, glob_name, check_proc)
|
514
|
+
break
|
515
|
+
end
|
516
|
+
end
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
if ld_path
|
522
|
+
nls_data_ext ||= so_ext # nls_data_ext is same with so_ext by default.
|
523
|
+
nls_data_basename.each do |basename|
|
524
|
+
if File.exist?(File.join(ld_path, "#{basename}.#{nls_data_ext}"))
|
525
|
+
puts " #{file} looks like an instant client."
|
526
|
+
return ld_path
|
527
|
+
end
|
528
|
+
end
|
529
|
+
puts " #{file} looks like a full client."
|
530
|
+
end
|
531
|
+
nil
|
532
|
+
end
|
533
|
+
|
534
|
+
def self.check_lib_in_path(paths, glob_name, check_proc)
|
535
|
+
paths.split(File::PATH_SEPARATOR).each do |path|
|
536
|
+
next if path.nil? or path == ''
|
537
|
+
print " checking #{path}... "
|
538
|
+
path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
|
539
|
+
files = Dir.glob(File.join(path, glob_name))
|
540
|
+
if files.empty?
|
541
|
+
puts "no"
|
542
|
+
next
|
543
|
+
end
|
544
|
+
STDOUT.flush
|
545
|
+
next if (check_proc && !check_proc.call(files[0]))
|
546
|
+
puts "yes"
|
547
|
+
return path, files[0]
|
548
|
+
end
|
549
|
+
nil
|
550
|
+
end
|
551
|
+
|
552
|
+
def init
|
553
|
+
check_cc()
|
554
|
+
@cc_is_gcc = check_cc_is_gcc()
|
555
|
+
@lp64 = check_lp64()
|
556
|
+
check_system_header()
|
557
|
+
check_ruby_header()
|
558
|
+
end
|
559
|
+
|
560
|
+
def check_cc
|
561
|
+
print "checking for cc... "
|
562
|
+
STDOUT.flush
|
563
|
+
if try_run("int main() { return 0; }")
|
564
|
+
puts "ok"
|
565
|
+
else
|
566
|
+
puts "ng"
|
567
|
+
raise "C compiler doesn't work correctly."
|
568
|
+
end
|
569
|
+
end # check_cc
|
570
|
+
|
571
|
+
def check_cc_is_gcc
|
572
|
+
# bcc defines __GNUC__. why??
|
573
|
+
return false if RUBY_PLATFORM =~ /bccwin32/
|
574
|
+
|
575
|
+
print "checking for gcc... "
|
576
|
+
STDOUT.flush
|
577
|
+
if macro_defined?("__GNUC__", "")
|
578
|
+
print "yes\n"
|
579
|
+
return true
|
580
|
+
else
|
581
|
+
print "no\n"
|
582
|
+
return false
|
583
|
+
end
|
584
|
+
end # check_cc_is_gcc
|
585
|
+
|
586
|
+
def check_lp64
|
587
|
+
print "checking for LP64... "
|
588
|
+
STDOUT.flush
|
589
|
+
if try_run("int main() { return sizeof(long) == 8 ? 0 : 1; }")
|
590
|
+
puts "yes"
|
591
|
+
true
|
592
|
+
else
|
593
|
+
puts "no"
|
594
|
+
false
|
595
|
+
end
|
596
|
+
end # check_lp64
|
597
|
+
|
598
|
+
def check_system_header
|
599
|
+
if not have_header('sys/types.h')
|
600
|
+
raise <<EOS
|
601
|
+
A standard C header file 'sys/types.h' doesn't exist.
|
602
|
+
Did you install glibc-devel(redhat) or libc6-dev(debian/ubuntu)?
|
603
|
+
EOS
|
604
|
+
end
|
605
|
+
end
|
606
|
+
|
607
|
+
def check_ruby_header
|
608
|
+
print "checking for ruby header... "
|
609
|
+
STDOUT.flush
|
610
|
+
rubyhdrdir = RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG['archdir']
|
611
|
+
unless File.exist?(rubyhdrdir + '/ruby.h')
|
612
|
+
puts "ng"
|
613
|
+
if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{RbConfig::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
|
614
|
+
raise <<EOS
|
615
|
+
#{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
|
616
|
+
Run the following commands to fix the problem.
|
617
|
+
|
618
|
+
cd #{RbConfig::CONFIG['archdir']}
|
619
|
+
sudo ln -s ../universal-darwin8.0/* ./
|
620
|
+
EOS
|
621
|
+
else
|
622
|
+
raise <<EOS
|
623
|
+
#{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
|
624
|
+
Install the ruby development library.
|
625
|
+
EOS
|
626
|
+
end
|
627
|
+
end
|
628
|
+
puts "ok"
|
629
|
+
$stdout.flush
|
630
|
+
end # check_ruby_header
|
631
|
+
|
632
|
+
def try_link_oci
|
633
|
+
original_libs = $libs
|
634
|
+
begin
|
635
|
+
$libs += " -L#{CONFIG['libdir']} " + @libs
|
636
|
+
have_func("OCIInitialize", "oci.h")
|
637
|
+
ensure
|
638
|
+
$libs = original_libs
|
639
|
+
end
|
640
|
+
end
|
641
|
+
|
642
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
643
|
+
|
644
|
+
def get_libs(base_dir = oci_base_dir)
|
645
|
+
case RUBY_PLATFORM
|
646
|
+
when /cygwin/
|
647
|
+
open("OCI.def", "w") do |f|
|
648
|
+
f.puts("EXPORTS")
|
649
|
+
open("|nm #{base_dir}/LIB/MSVC/OCI.LIB") do |r|
|
650
|
+
while line = r.gets
|
651
|
+
f.puts($') if line =~ / T _/
|
652
|
+
end
|
653
|
+
end
|
654
|
+
end
|
655
|
+
command = "dlltool -d OCI.def -D OCI.DLL -l libOCI.a"
|
656
|
+
print("Running: '#{command}' ...")
|
657
|
+
STDOUT.flush
|
658
|
+
system(command)
|
659
|
+
puts("done")
|
660
|
+
"-L. -lOCI"
|
661
|
+
when /bccwin32/
|
662
|
+
# replace '/' to '\\' because bcc linker misunderstands
|
663
|
+
# 'C:/foo/bar/OCI.LIB' as unknown option.
|
664
|
+
lib = "#{base_dir}/LIB/BORLAND/OCI.LIB"
|
665
|
+
return lib.tr('/', '\\') if File.exist?(lib)
|
666
|
+
raise <<EOS
|
667
|
+
#{lib} does not exist.
|
668
|
+
|
669
|
+
Your Oracle may not support Borland C++.
|
670
|
+
If you want to run this module, run the following command at your own risk.
|
671
|
+
cd #{base_dir.tr('/', '\\')}\\LIB
|
672
|
+
mkdir Borland
|
673
|
+
cd Borland
|
674
|
+
coff2omf ..\\MSVC\\OCI.LIB OCI.LIB
|
675
|
+
EOS
|
676
|
+
exit 1
|
677
|
+
else
|
678
|
+
"\"#{base_dir}/LIB/MSVC/OCI.LIB\""
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
else
|
683
|
+
# Unix
|
684
|
+
def get_libs(lib_dir)
|
685
|
+
case RUBY_PLATFORM
|
686
|
+
when /solaris/
|
687
|
+
" -L#{lib_dir} -R#{lib_dir} -lclntsh"
|
688
|
+
when /linux/
|
689
|
+
" -L#{lib_dir} -Wl,-rpath,#{lib_dir} -lclntsh"
|
690
|
+
else
|
691
|
+
" -L#{lib_dir} -lclntsh"
|
692
|
+
end
|
693
|
+
end
|
694
|
+
|
695
|
+
end
|
696
|
+
end
|
697
|
+
|
698
|
+
# OraConf for Full Client
|
699
|
+
class OraConfFC < OraConf
|
700
|
+
def initialize
|
701
|
+
init
|
702
|
+
|
703
|
+
@oracle_home = get_home()
|
704
|
+
if RUBY_PLATFORM =~ /freebsd/ && @oracle_home == '/usr/local/oracle8-client'
|
705
|
+
@version = '817'
|
706
|
+
else
|
707
|
+
@version = get_version()
|
708
|
+
end
|
709
|
+
@cflags = get_cflags()
|
710
|
+
$CFLAGS += @cflags
|
711
|
+
|
712
|
+
if !@lp64 && File.exist?("#{@oracle_home}/lib32")
|
713
|
+
# ruby - 32bit
|
714
|
+
# oracle - 64bit
|
715
|
+
use_lib32 = true
|
716
|
+
else
|
717
|
+
use_lib32 = false
|
718
|
+
end
|
719
|
+
|
720
|
+
if use_lib32
|
721
|
+
lib_dir = "#{@oracle_home}/lib32"
|
722
|
+
else
|
723
|
+
lib_dir = "#{@oracle_home}/lib"
|
724
|
+
end
|
725
|
+
@libs = get_libs(lib_dir)
|
726
|
+
return if try_link_oci()
|
727
|
+
|
728
|
+
raise 'cannot compile OCI'
|
729
|
+
end
|
730
|
+
|
731
|
+
private
|
732
|
+
|
733
|
+
def get_version
|
734
|
+
print("Get the version of Oracle from SQL*Plus... ")
|
735
|
+
STDOUT.flush
|
736
|
+
version = nil
|
737
|
+
dev_null = RUBY_PLATFORM =~ /mswin32|mingw32|bccwin32/ ? "nul" : "/dev/null"
|
738
|
+
if File.exist?("#{@oracle_home}/bin/plus80.exe")
|
739
|
+
sqlplus = "plus80.exe"
|
740
|
+
else
|
741
|
+
sqlplus = "sqlplus"
|
742
|
+
end
|
743
|
+
Logging::open do
|
744
|
+
ENV['NLS_LANG'] = 'american_america.us7ascii'
|
745
|
+
open("|#{@oracle_home}/bin/#{sqlplus} < #{dev_null}") do |f|
|
746
|
+
while line = f.gets
|
747
|
+
print line
|
748
|
+
if line =~ /(\d+)\.(\d)\.(\d)/
|
749
|
+
version = $1 + $2 + $3
|
750
|
+
break
|
751
|
+
end
|
752
|
+
end
|
753
|
+
end
|
754
|
+
end
|
755
|
+
if version.nil?
|
756
|
+
raise 'cannot get Oracle version from sqlplus'
|
757
|
+
end
|
758
|
+
puts version
|
759
|
+
version
|
760
|
+
end # get_version
|
761
|
+
|
762
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
763
|
+
|
764
|
+
def is_valid_home?(oracle_home)
|
765
|
+
return false if oracle_home.nil?
|
766
|
+
sqlplus = "#{oracle_home}/bin/sqlplus.exe"
|
767
|
+
print("checking for ORACLE_HOME(#{oracle_home})... ")
|
768
|
+
STDOUT.flush
|
769
|
+
if File.exist?(sqlplus)
|
770
|
+
puts("yes")
|
771
|
+
true
|
772
|
+
else
|
773
|
+
puts("no")
|
774
|
+
false
|
775
|
+
end
|
776
|
+
end
|
777
|
+
|
778
|
+
def get_home()
|
779
|
+
oracle_home = ENV['ORACLE_HOME']
|
780
|
+
if oracle_home.nil?
|
781
|
+
struct = Struct.new("OracleHome", :name, :path)
|
782
|
+
oracle_homes = []
|
783
|
+
MiniRegistry.enum_homes do |name, path|
|
784
|
+
path.chomp!("\\") if path
|
785
|
+
oracle_homes << struct.new(name, path) if is_valid_home?(path)
|
786
|
+
end
|
787
|
+
if oracle_homes.empty?
|
788
|
+
raise <<EOS
|
789
|
+
Set the environment variable ORACLE_HOME if Oracle Full Client.
|
790
|
+
Append the path of Oracle client libraries to #{OraConf.ld_envs[0]} if Oracle Instant Client.
|
791
|
+
EOS
|
792
|
+
end
|
793
|
+
if oracle_homes.length == 1
|
794
|
+
oracle_home = oracle_homes[0].path
|
795
|
+
else
|
796
|
+
default_path = ''
|
797
|
+
if RUBY_PLATFORM =~ /cygwin/
|
798
|
+
path_sep = ':'
|
799
|
+
dir_sep = '/'
|
800
|
+
else
|
801
|
+
path_sep = ';'
|
802
|
+
dir_sep = '\\'
|
803
|
+
end
|
804
|
+
ENV['PATH'].split(path_sep).each do |path|
|
805
|
+
path.chomp!(dir_sep)
|
806
|
+
if File.exist?("#{path}/OCI.DLL")
|
807
|
+
default_path = path
|
808
|
+
break
|
809
|
+
end
|
810
|
+
end
|
811
|
+
puts "---------------------------------------------------"
|
812
|
+
puts "Multiple Oracle Homes are found."
|
813
|
+
printf " %-15s : %s\n", "[NAME]", "[PATH]"
|
814
|
+
oracle_homes.each do |home|
|
815
|
+
if RUBY_PLATFORM =~ /cygwin/
|
816
|
+
path = `cygpath -u '#{home.path}'`.chomp!
|
817
|
+
else
|
818
|
+
path = home.path
|
819
|
+
end
|
820
|
+
if default_path.downcase == "#{path.downcase}#{dir_sep}bin"
|
821
|
+
oracle_home = home
|
822
|
+
end
|
823
|
+
printf " %-15s : %s\n", home.name, home.path
|
824
|
+
end
|
825
|
+
if oracle_home.nil?
|
826
|
+
puts "default oracle home is not found."
|
827
|
+
puts "---------------------------------------------------"
|
828
|
+
raise 'Cannot get ORACLE_HOME. Please set the environment valiable ORACLE_HOME.'
|
829
|
+
else
|
830
|
+
printf "use %s\n", oracle_home.name
|
831
|
+
puts "run ohsel.exe to use another oracle home."
|
832
|
+
puts "---------------------------------------------------"
|
833
|
+
oracle_home = oracle_home.path
|
834
|
+
end
|
835
|
+
end
|
836
|
+
end
|
837
|
+
if RUBY_PLATFORM =~ /cygwin/
|
838
|
+
oracle_home = oracle_home.sub(/^([a-zA-Z]):/, "/cygdrive/\\1")
|
839
|
+
end
|
840
|
+
oracle_home.gsub(/\\/, '/')
|
841
|
+
end
|
842
|
+
|
843
|
+
def oci_base_dir
|
844
|
+
case @version
|
845
|
+
when /80./
|
846
|
+
"#{@oracle_home}/OCI80"
|
847
|
+
else
|
848
|
+
"#{@oracle_home}/OCI"
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
def get_cflags
|
853
|
+
unless File.exist?("#{oci_base_dir}/INCLUDE/OCI.H")
|
854
|
+
raise "'#{oci_base_dir}/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
|
855
|
+
end
|
856
|
+
if RUBY_PLATFORM =~ /cygwin/
|
857
|
+
" \"-I#{oci_base_dir}/INCLUDE\" -D_int64=\"long long\""
|
858
|
+
else
|
859
|
+
" \"-I#{oci_base_dir}/INCLUDE\""
|
860
|
+
end
|
861
|
+
end
|
862
|
+
|
863
|
+
else # when UNIX
|
864
|
+
|
865
|
+
def get_home
|
866
|
+
oracle_home = ENV['ORACLE_HOME']
|
867
|
+
if oracle_home.nil?
|
868
|
+
msg = <<EOS
|
869
|
+
Set the environment variable ORACLE_HOME if Oracle Full Client.
|
870
|
+
Append the path of Oracle client libraries to #{OraConf.ld_envs[0]} if Oracle Instant Client.
|
871
|
+
EOS
|
872
|
+
|
873
|
+
# check sudo environment
|
874
|
+
sudo_command = ENV['SUDO_COMMAND']
|
875
|
+
if /\w*make\b/ =~ sudo_command
|
876
|
+
msg += <<EOS
|
877
|
+
|
878
|
+
The 'sudo' command unset some environment variables for security reasons.
|
879
|
+
Use it only when running 'make install' as follows
|
880
|
+
make
|
881
|
+
sudo make install
|
882
|
+
EOS
|
883
|
+
end
|
884
|
+
if /\w+\/gem\b/ =~ sudo_command
|
885
|
+
msg += <<EOS
|
886
|
+
|
887
|
+
The 'sudo' command unset some environment variables for security reasons.
|
888
|
+
Pass required varialbes as follows
|
889
|
+
sudo env #{OraConf.ld_envs[0]}=$#{OraConf.ld_envs[0]} #{sudo_command}
|
890
|
+
or
|
891
|
+
sudo env ORACLE_HOME=$ORACLE_HOME #{sudo_command}
|
892
|
+
EOS
|
893
|
+
end
|
894
|
+
raise msg
|
895
|
+
end
|
896
|
+
oracle_home
|
897
|
+
end
|
898
|
+
|
899
|
+
def get_cflags
|
900
|
+
cflags = ''
|
901
|
+
ok = false
|
902
|
+
original_CFLAGS = $CFLAGS
|
903
|
+
begin
|
904
|
+
for i in ["rdbms/public", "rdbms/demo", "network/public", "plsql/public"]
|
905
|
+
cflags += " -I#{@oracle_home}/#{i}"
|
906
|
+
$CFLAGS += " -I#{@oracle_home}/#{i}"
|
907
|
+
print("try #{cflags}\n");
|
908
|
+
if have_header("oci.h")
|
909
|
+
ok = true
|
910
|
+
break
|
911
|
+
end
|
912
|
+
end
|
913
|
+
unless ok
|
914
|
+
if @version.to_i >= 1000
|
915
|
+
oci_h = "#{@oracle_home}/rdbms/public/oci.h"
|
916
|
+
else
|
917
|
+
oci_h = "#{@oracle_home}/rdbms/demo/oci.h"
|
918
|
+
end
|
919
|
+
unless File.exist?(oci_h)
|
920
|
+
raise "'#{oci_h}' does not exists. Install 'Oracle Call Interface' component."
|
921
|
+
end
|
922
|
+
raise 'Cannot get proper cflags.'
|
923
|
+
end
|
924
|
+
cflags
|
925
|
+
ensure
|
926
|
+
$CFLAGS = original_CFLAGS
|
927
|
+
end
|
928
|
+
end # get_cflags
|
929
|
+
|
930
|
+
end
|
931
|
+
end
|
932
|
+
|
933
|
+
# OraConf for Instant Client
|
934
|
+
class OraConfIC < OraConf
|
935
|
+
def initialize(ic_dir)
|
936
|
+
init
|
937
|
+
|
938
|
+
if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+(?:\.\d+)*)\/client(64)?\/lib(?:64)?/
|
939
|
+
# rpm package
|
940
|
+
# x86 rpms after 11.1.0.7.0:
|
941
|
+
# library: /usr/lib/oracle/X.X/client/lib/
|
942
|
+
# include: /usr/include/oracle/X.X/client/
|
943
|
+
#
|
944
|
+
# x86_64 rpms after 11.1.0.7.0:
|
945
|
+
# library: /usr/lib/oracle/X.X/client64/lib/
|
946
|
+
# include: /usr/include/oracle/X.X/client64/
|
947
|
+
#
|
948
|
+
# x86 rpms before 11.1.0.6.0:
|
949
|
+
# library: /usr/lib/oracle/X.X.X.X/client/lib/
|
950
|
+
# include: /usr/include/oracle/X.X.X.X/client/
|
951
|
+
#
|
952
|
+
# x86_64 rpms before 11.1.0.6.0:
|
953
|
+
# library: /usr/lib/oracle/X.X.X.X/client64/lib/
|
954
|
+
# include: /usr/include/oracle/X.X.X.X/client64/
|
955
|
+
#
|
956
|
+
# third-party x86_64 rpms(*1):
|
957
|
+
# library: /usr/lib64/oracle/X.X.X.X/client/lib/
|
958
|
+
# or /usr/lib64/oracle/X.X.X.X/client/lib64/
|
959
|
+
# include: /usr/include/oracle/X.X.X.X/client/
|
960
|
+
#
|
961
|
+
# *1 These had been used before Oracle released official x86_64 rpms.
|
962
|
+
#
|
963
|
+
lib_dir = ic_dir
|
964
|
+
inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
|
965
|
+
else
|
966
|
+
# zip package
|
967
|
+
lib_dir = ic_dir
|
968
|
+
inc_dir = "#{ic_dir}/sdk/include"
|
969
|
+
end
|
970
|
+
|
971
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
972
|
+
unless File.exist?("#{ic_dir}/sdk/lib/msvc/oci.lib")
|
973
|
+
raise <<EOS
|
974
|
+
Could not compile with Oracle instant client.
|
975
|
+
#{ic_dir}/sdk/lib/msvc/oci.lib could not be found.
|
976
|
+
EOS
|
977
|
+
raise 'failed'
|
978
|
+
end
|
979
|
+
@cflags = " \"-I#{inc_dir}\""
|
980
|
+
@cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin/
|
981
|
+
@libs = get_libs("#{ic_dir}/sdk")
|
982
|
+
ld_path = nil
|
983
|
+
else
|
984
|
+
@cflags = " -I#{inc_dir}"
|
985
|
+
# set ld_path and so_ext
|
986
|
+
case RUBY_PLATFORM
|
987
|
+
when /aix/
|
988
|
+
ld_path = 'LIBPATH'
|
989
|
+
so_ext = 'a'
|
990
|
+
when /hppa.*-hpux/
|
991
|
+
if @lp64
|
992
|
+
ld_path = 'LD_LIBRARY_PATH'
|
993
|
+
else
|
994
|
+
ld_path = 'SHLIB_PATH'
|
995
|
+
end
|
996
|
+
so_ext = 'sl'
|
997
|
+
when /darwin/
|
998
|
+
ld_path = 'DYLD_LIBRARY_PATH'
|
999
|
+
so_ext = 'dylib'
|
1000
|
+
else
|
1001
|
+
ld_path = 'LD_LIBRARY_PATH'
|
1002
|
+
so_ext = 'so'
|
1003
|
+
end
|
1004
|
+
# check Oracle client library.
|
1005
|
+
unless File.exist?("#{lib_dir}/libclntsh.#{so_ext}")
|
1006
|
+
files = Dir.glob("#{lib_dir}/libclntsh.#{so_ext}.*")
|
1007
|
+
if files.empty?
|
1008
|
+
raise <<EOS
|
1009
|
+
Could not compile with Oracle instant client.
|
1010
|
+
'#{lib_dir}/libclntsh.#{so_ext}' could not be found.
|
1011
|
+
Did you install instantclient-basic?
|
1012
|
+
EOS
|
1013
|
+
else
|
1014
|
+
file = File.basename(files.sort[-1])
|
1015
|
+
raise <<EOS
|
1016
|
+
Could not compile with Oracle instant client.
|
1017
|
+
#{lib_dir}/libclntsh.#{so_ext} could not be found.
|
1018
|
+
You may need to make a symbolic link.
|
1019
|
+
cd #{lib_dir}
|
1020
|
+
ln -s #{file} libclntsh.#{so_ext}
|
1021
|
+
EOS
|
1022
|
+
end
|
1023
|
+
raise 'failed'
|
1024
|
+
end
|
1025
|
+
@libs = get_libs(lib_dir)
|
1026
|
+
end
|
1027
|
+
unless File.exist?("#{inc_dir}/oci.h")
|
1028
|
+
raise <<EOS
|
1029
|
+
'#{inc_dir}/oci.h' does not exist.
|
1030
|
+
Install 'Instant Client SDK'.
|
1031
|
+
EOS
|
1032
|
+
end
|
1033
|
+
$CFLAGS += @cflags
|
1034
|
+
if try_link_oci()
|
1035
|
+
major = try_constant("OCI_MAJOR_VERSION", "oci.h")
|
1036
|
+
minor = try_constant("OCI_MINOR_VERSION", "oci.h")
|
1037
|
+
if major and minor
|
1038
|
+
@version = format('%d%d0', major, minor)
|
1039
|
+
else
|
1040
|
+
# 10.1.0 doesn't have OCI_MAJOR_VERSION and OCI_MINOR_VERSION in oci.h.
|
1041
|
+
@version = "1010"
|
1042
|
+
if RUBY_PLATFORM =~ /darwin/ and 1.size == 8 and `sw_vers -productVersion`.chomp == "10.7"
|
1043
|
+
$stderr.print <<EOS
|
1044
|
+
WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
|
1045
|
+
|
1046
|
+
64-bit Oracle instant client doesn't work on OS X Lion.
|
1047
|
+
See: https://forums.oracle.com/forums/thread.jspa?threadID=2187558
|
1048
|
+
|
1049
|
+
The compilation is continued because the issue may be fixed in future.
|
1050
|
+
|
1051
|
+
WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
|
1052
|
+
EOS
|
1053
|
+
end
|
1054
|
+
end
|
1055
|
+
return
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
if RUBY_PLATFORM =~ /darwin/
|
1059
|
+
open('mkmf.log', 'r') do |f|
|
1060
|
+
while line = f.gets
|
1061
|
+
if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
|
1062
|
+
raise <<EOS
|
1063
|
+
Intel mac instant client is for Mac OS X 10.5.
|
1064
|
+
It doesn't work on Mac OS X 10.4 or before.
|
1065
|
+
|
1066
|
+
You have three workarounds.
|
1067
|
+
1. Compile ruby as ppc binary and use it with ppc instant client.
|
1068
|
+
2. Use JRuby and JDBC
|
1069
|
+
3. Use a third-party ODBC driver and ruby-odbc.
|
1070
|
+
EOS
|
1071
|
+
# '
|
1072
|
+
end
|
1073
|
+
|
1074
|
+
case line
|
1075
|
+
when /cputype \(\d+, architecture \w+\) does not match cputype \(\d+\) for specified -arch flag: (\w+)/
|
1076
|
+
missing_arch = $1
|
1077
|
+
when /Undefined symbols for architecture (\w+)/
|
1078
|
+
missing_arch = $1
|
1079
|
+
when /missing required architecture (\w+) in file/
|
1080
|
+
missing_arch = $1
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
if missing_arch
|
1084
|
+
if [nil].pack('p').size == 8
|
1085
|
+
my_arch = 'x86_64'
|
1086
|
+
elsif "\x01\x02".unpack('s')[0] == 0x0201
|
1087
|
+
my_arch = 'i386'
|
1088
|
+
else
|
1089
|
+
my_arch = 'ppc'
|
1090
|
+
end
|
1091
|
+
raise <<EOS
|
1092
|
+
Could not compile with Oracle instant client.
|
1093
|
+
You may need to set the environment variable RC_ARCHS or ARCHFLAGS as follows:
|
1094
|
+
|
1095
|
+
RC_ARCHS=#{my_arch}
|
1096
|
+
export RC_ARCHS
|
1097
|
+
or
|
1098
|
+
ARCHFLAGS='-arch #{my_arch}'
|
1099
|
+
export RC_ARCHS
|
1100
|
+
|
1101
|
+
If it does not fix the problem, delete all '-arch #{missing_arch}'
|
1102
|
+
in '#{RbConfig::CONFIG['archdir']}/rbconfig.rb'.
|
1103
|
+
EOS
|
1104
|
+
end
|
1105
|
+
end
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
unless ld_path.nil?
|
1110
|
+
raise <<EOS
|
1111
|
+
Could not compile with Oracle instant client.
|
1112
|
+
You may need to set a environment variable:
|
1113
|
+
#{ld_path}=#{lib_dir}
|
1114
|
+
export #{ld_path}
|
1115
|
+
EOS
|
1116
|
+
end
|
1117
|
+
raise 'failed'
|
1118
|
+
end
|
1119
|
+
end
|