ruby-oci8 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +569 -0
- data/Makefile +51 -0
- data/NEWS +322 -0
- data/README +415 -0
- data/VERSION +1 -0
- data/dist-files +70 -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/MANIFEST +22 -0
- data/ext/oci8/attr.c +415 -0
- data/ext/oci8/bind.c +194 -0
- data/ext/oci8/const.c +165 -0
- data/ext/oci8/define.c +53 -0
- data/ext/oci8/describe.c +81 -0
- data/ext/oci8/descriptor.c +39 -0
- data/ext/oci8/env.c +276 -0
- data/ext/oci8/error.c +234 -0
- data/ext/oci8/extconf.rb +118 -0
- data/ext/oci8/handle.c +262 -0
- data/ext/oci8/lob.c +386 -0
- data/ext/oci8/oci8.c +137 -0
- data/ext/oci8/oci8.h +345 -0
- data/ext/oci8/ocinumber.c +117 -0
- data/ext/oci8/oraconf.rb +1026 -0
- data/ext/oci8/oradate.c +426 -0
- data/ext/oci8/oranumber.c +445 -0
- data/ext/oci8/param.c +37 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/server.c +182 -0
- data/ext/oci8/session.c +99 -0
- data/ext/oci8/stmt.c +624 -0
- data/ext/oci8/svcctx.c +229 -0
- data/lib/DBD/OCI8/OCI8.rb +549 -0
- data/lib/oci8.rb.in +1605 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +54 -0
- data/ruby-oci8.spec +62 -0
- data/setup.rb +1331 -0
- data/support/README +4 -0
- data/support/runit/assert.rb +281 -0
- data/support/runit/cui/testrunner.rb +101 -0
- data/support/runit/error.rb +4 -0
- data/support/runit/method_mappable.rb +20 -0
- data/support/runit/robserver.rb +25 -0
- data/support/runit/setuppable.rb +15 -0
- data/support/runit/teardownable.rb +16 -0
- data/support/runit/testcase.rb +113 -0
- data/support/runit/testfailure.rb +25 -0
- data/support/runit/testresult.rb +121 -0
- data/support/runit/testsuite.rb +43 -0
- data/support/runit/version.rb +3 -0
- data/test/README +4 -0
- data/test/config.rb +129 -0
- data/test/test_all.rb +43 -0
- data/test/test_bind_raw.rb +53 -0
- data/test/test_bind_time.rb +191 -0
- data/test/test_break.rb +81 -0
- data/test/test_clob.rb +101 -0
- data/test/test_connstr.rb +80 -0
- data/test/test_dbi.rb +317 -0
- data/test/test_dbi_clob.rb +56 -0
- data/test/test_describe.rb +137 -0
- data/test/test_metadata.rb +243 -0
- data/test/test_oci8.rb +273 -0
- data/test/test_oradate.rb +263 -0
- data/test/test_oranumber.rb +149 -0
- metadata +118 -0
@@ -0,0 +1,117 @@
|
|
1
|
+
/*
|
2
|
+
ocinumber.c - part of ruby-oci8
|
3
|
+
copy from ocinumber.c in ruby-oci8 0.2.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "oci8.h"
|
7
|
+
#include <orl.h>
|
8
|
+
|
9
|
+
/* use for local call */
|
10
|
+
#define oci_lc(rv) do { \
|
11
|
+
sword __rv = (rv); \
|
12
|
+
if (__rv != OCI_SUCCESS) { \
|
13
|
+
oci8_raise(errhp, __rv, NULL); \
|
14
|
+
} \
|
15
|
+
} while(0)
|
16
|
+
|
17
|
+
#define NUMBER_FORMAT1_STR "FM9999999999999999999999990.9999999999999999999999999999999999999"
|
18
|
+
#define NUMBER_FORMAT1 (OraText*)NUMBER_FORMAT1_STR
|
19
|
+
#define NUMBER_FORMAT1_LEN (sizeof(NUMBER_FORMAT1_STR) - 1)
|
20
|
+
#define NUMBER_FORMAT2_STR "FM99999999999999999999999999999999999990.999999999999999999999999"
|
21
|
+
#define NUMBER_FORMAT2 (OraText*)NUMBER_FORMAT2_STR
|
22
|
+
#define NUMBER_FORMAT2_LEN (sizeof(NUMBER_FORMAT2_STR) - 1)
|
23
|
+
#define NUMBER_FORMAT2_DECIMAL (sizeof("999999999999999999999999") - 1)
|
24
|
+
#define NUMBER_FORMAT_INT_STR "FM99999999999999999999999999999999999990"
|
25
|
+
#define NUMBER_FORMAT_INT (OraText*)NUMBER_FORMAT_INT_STR
|
26
|
+
#define NUMBER_FORMAT_INT_LEN (sizeof(NUMBER_FORMAT_INT_STR) - 1)
|
27
|
+
|
28
|
+
#ifndef StringValue
|
29
|
+
#define StringValue(s) ((s) = (TYPE(s) == T_STRING) ? (s) : rb_str_to_str(s))
|
30
|
+
#endif
|
31
|
+
|
32
|
+
/* fill C structure (OCINumber) from a string. */
|
33
|
+
static void set_oci_number_from_str(OCINumber *result, VALUE str, VALUE fmt, VALUE nls_params, OCIError *errhp)
|
34
|
+
{
|
35
|
+
oratext *fmt_ptr;
|
36
|
+
oratext *nls_params_ptr;
|
37
|
+
ub4 fmt_len;
|
38
|
+
ub4 nls_params_len;
|
39
|
+
|
40
|
+
StringValue(str);
|
41
|
+
/* set from string. */
|
42
|
+
if (NIL_P(fmt)) {
|
43
|
+
int i, cnt = 0;
|
44
|
+
for (i = RSTRING_LEN(str) - 1; i >= 0; i--) {
|
45
|
+
if (RSTRING_PTR(str)[i] != ' ')
|
46
|
+
cnt++;
|
47
|
+
if (RSTRING_PTR(str)[i] == '.') {
|
48
|
+
i = RSTRING_LEN(str) - i;
|
49
|
+
break;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
if (i == -1)
|
53
|
+
cnt = 0;
|
54
|
+
if (cnt <= NUMBER_FORMAT2_DECIMAL) {
|
55
|
+
fmt_ptr = NUMBER_FORMAT2;
|
56
|
+
fmt_len = NUMBER_FORMAT2_LEN;
|
57
|
+
} else {
|
58
|
+
fmt_ptr = NUMBER_FORMAT1;
|
59
|
+
fmt_len = NUMBER_FORMAT1_LEN;
|
60
|
+
}
|
61
|
+
} else {
|
62
|
+
StringValue(fmt);
|
63
|
+
fmt_ptr = RSTRING_ORATEXT(fmt);
|
64
|
+
fmt_len = RSTRING_LEN(fmt);
|
65
|
+
}
|
66
|
+
if (NIL_P(nls_params)) {
|
67
|
+
nls_params_ptr = NULL;
|
68
|
+
nls_params_len = 0;
|
69
|
+
} else {
|
70
|
+
StringValue(nls_params);
|
71
|
+
nls_params_ptr = RSTRING_ORATEXT(nls_params);
|
72
|
+
nls_params_len = RSTRING_LEN(nls_params);
|
73
|
+
}
|
74
|
+
oci_lc(OCINumberFromText(errhp,
|
75
|
+
RSTRING_ORATEXT(str), RSTRING_LEN(str),
|
76
|
+
fmt_ptr, fmt_len, nls_params_ptr, nls_params_len,
|
77
|
+
result));
|
78
|
+
}
|
79
|
+
|
80
|
+
/* fill C structure (OCINumber) from a numeric object. */
|
81
|
+
/* 1 - success, 0 - error */
|
82
|
+
static int set_oci_number_from_num(OCINumber *result, VALUE num, OCIError *errhp)
|
83
|
+
{
|
84
|
+
signed long sl;
|
85
|
+
double dbl;
|
86
|
+
|
87
|
+
if (!RTEST(rb_obj_is_kind_of(num, rb_cNumeric)))
|
88
|
+
rb_raise(rb_eTypeError, "expect Numeric but %s", rb_class2name(CLASS_OF(num)));
|
89
|
+
switch (rb_type(num)) {
|
90
|
+
case T_FIXNUM:
|
91
|
+
/* set from long. */
|
92
|
+
sl = NUM2LONG(num);
|
93
|
+
oci_lc(OCINumberFromInt(errhp, &sl, sizeof(sl), OCI_NUMBER_SIGNED, result));
|
94
|
+
return 1;
|
95
|
+
case T_FLOAT:
|
96
|
+
/* set from double. */
|
97
|
+
dbl = NUM2DBL(num);
|
98
|
+
oci_lc(OCINumberFromReal(errhp, &dbl, sizeof(dbl), result));
|
99
|
+
return 1;
|
100
|
+
case T_BIGNUM:
|
101
|
+
/* change via string. */
|
102
|
+
num = rb_big2str(num, 10);
|
103
|
+
set_oci_number_from_str(result, num, Qnil, Qnil, errhp);
|
104
|
+
return 1;
|
105
|
+
}
|
106
|
+
if (RTEST(rb_obj_is_instance_of(num, cOraNumber))) {
|
107
|
+
/* OCI::Number */
|
108
|
+
oci_lc(OCINumberAssign(errhp, DATA_PTR(num), result));
|
109
|
+
return 1;
|
110
|
+
}
|
111
|
+
return 0;
|
112
|
+
}
|
113
|
+
|
114
|
+
int set_oci_vnumber(ora_vnumber_t *result, VALUE num, OCIError *errhp)
|
115
|
+
{
|
116
|
+
return set_oci_number_from_num((OCINumber*)result, num, errhp);
|
117
|
+
}
|
data/ext/oci8/oraconf.rb
ADDED
@@ -0,0 +1,1026 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
unless defined? macro_defined?
|
4
|
+
# ruby 1.6 doesn't have 'macro_defined?'.
|
5
|
+
def macro_defined?(macro, src, opt="")
|
6
|
+
try_cpp(src + <<"SRC", opt)
|
7
|
+
#ifndef #{macro}
|
8
|
+
# error
|
9
|
+
#endif
|
10
|
+
SRC
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Logging
|
15
|
+
unless Logging.respond_to?(:open)
|
16
|
+
# emulate Logging::open of ruby 1.6.8 or later.
|
17
|
+
|
18
|
+
if $log.nil? # ruby 1.6.2 doesn't have $log.
|
19
|
+
$log = open('mkmf.log', 'w')
|
20
|
+
end
|
21
|
+
def Logging::open
|
22
|
+
begin
|
23
|
+
$stderr.reopen($log)
|
24
|
+
$stdout.reopen($log)
|
25
|
+
yield
|
26
|
+
ensure
|
27
|
+
$stderr.reopen($orgerr)
|
28
|
+
$stdout.reopen($orgout)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end # module Logging
|
33
|
+
|
34
|
+
module MiniRegistry
|
35
|
+
class MiniRegistryError < StandardError
|
36
|
+
attr_reader :api_name
|
37
|
+
attr_reader :code
|
38
|
+
def initialize(api_name, code)
|
39
|
+
@api_name = api_name
|
40
|
+
@code = code
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
|
44
|
+
# Windows
|
45
|
+
require 'Win32API' # raise LoadError when UNIX.
|
46
|
+
|
47
|
+
# I looked in Win32Module by MoonWolf <URL:http://www.moonwolf.com/ruby/>,
|
48
|
+
# copy the minimum code and reorganize it.
|
49
|
+
ERROR_SUCCESS = 0
|
50
|
+
ERROR_FILE_NOT_FOUND = 2
|
51
|
+
|
52
|
+
HKEY_LOCAL_MACHINE = 0x80000002
|
53
|
+
RegOpenKeyExA = Win32API.new('advapi32', 'RegOpenKeyExA', 'LPLLP', 'L')
|
54
|
+
RegQueryValueExA = Win32API.new('advapi32','RegQueryValueExA','LPPPPP','L')
|
55
|
+
RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
|
56
|
+
|
57
|
+
def get_reg_value(root, subkey, name)
|
58
|
+
result = [0].pack('L')
|
59
|
+
code = RegOpenKeyExA.call(root, subkey, 0, 0x20019, result)
|
60
|
+
if code != ERROR_SUCCESS
|
61
|
+
raise MiniRegistryError.new("Win32::RegOpenKeyExA", code)
|
62
|
+
end
|
63
|
+
hkey = result.unpack('L')[0]
|
64
|
+
begin
|
65
|
+
lpcbData = [0].pack('L')
|
66
|
+
code = RegQueryValueExA.call(hkey, name, nil, nil, nil, lpcbData)
|
67
|
+
if code == ERROR_FILE_NOT_FOUND
|
68
|
+
return nil
|
69
|
+
elsif code != ERROR_SUCCESS
|
70
|
+
raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
|
71
|
+
end
|
72
|
+
len = lpcbData.unpack('L')[0]
|
73
|
+
lpType = "\0\0\0\0"
|
74
|
+
lpData = "\0"*len
|
75
|
+
lpcbData = [len].pack('L')
|
76
|
+
code = RegQueryValueExA.call(hkey, name, nil, lpType, lpData, lpcbData)
|
77
|
+
if code != ERROR_SUCCESS
|
78
|
+
raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
|
79
|
+
end
|
80
|
+
lpData.unpack('Z*')[0]
|
81
|
+
ensure
|
82
|
+
RegCloseKey.call(hkey)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
def get_local_registry(subkey, name)
|
86
|
+
get_reg_value(HKEY_LOCAL_MACHINE, subkey, name)
|
87
|
+
end
|
88
|
+
else
|
89
|
+
# UNIX
|
90
|
+
def get_local_registry(subkey, name)
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end # module MiniRegistry
|
95
|
+
|
96
|
+
# minimal implementation to read information of a shared object.
|
97
|
+
class MiniSOReader
|
98
|
+
attr_reader :file_format
|
99
|
+
attr_reader :cpu
|
100
|
+
attr_reader :endian
|
101
|
+
attr_reader :bits
|
102
|
+
|
103
|
+
def initialize(filename)
|
104
|
+
f = open(filename, 'rb')
|
105
|
+
begin
|
106
|
+
case file_header = f.read(2)
|
107
|
+
when "\177E"
|
108
|
+
# Linux, Solaris and HP-UX(64-bit)
|
109
|
+
read_elf(f) if f.read(2) == 'LF'
|
110
|
+
when "MZ"
|
111
|
+
# Windows
|
112
|
+
read_pe(f)
|
113
|
+
else
|
114
|
+
# HP-UX(32-bit), AIX, Mac OS X and Tru64
|
115
|
+
raise format("unknown file header: %02x %02x", file_header[0], file_header[1])
|
116
|
+
end
|
117
|
+
ensure
|
118
|
+
f.close
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
# ELF format
|
124
|
+
def read_elf(f)
|
125
|
+
# 0-3 "\177ELF"
|
126
|
+
@file_format = :elf
|
127
|
+
# 4
|
128
|
+
case f.read(1).unpack('C')[0]
|
129
|
+
when 1
|
130
|
+
@bits = 32
|
131
|
+
when 2
|
132
|
+
@bits = 64
|
133
|
+
else
|
134
|
+
raise 'Invalid ELF class'
|
135
|
+
end
|
136
|
+
# 5
|
137
|
+
case f.read(1).unpack('C')[0]
|
138
|
+
when 1
|
139
|
+
@endian = :little
|
140
|
+
pack_type_short = 'v'
|
141
|
+
when 2
|
142
|
+
@endian = :big
|
143
|
+
pack_type_short = 'n'
|
144
|
+
else
|
145
|
+
raise 'Invalid ELF byte order'
|
146
|
+
end
|
147
|
+
# 6
|
148
|
+
raise 'Invalid ELF header version' if f.read(1) != "\x01"
|
149
|
+
# 16-17
|
150
|
+
f.seek(16, IO::SEEK_SET)
|
151
|
+
raise 'Invalid ELF filetype' if f.read(2).unpack(pack_type_short)[0] != 3
|
152
|
+
# 18-19
|
153
|
+
case archtype = f.read(2).unpack(pack_type_short)[0]
|
154
|
+
when 2
|
155
|
+
@cpu = :sparc
|
156
|
+
when 3
|
157
|
+
@cpu = :i386
|
158
|
+
when 15
|
159
|
+
@cpu = :parisc
|
160
|
+
when 20
|
161
|
+
@cpu = :ppc
|
162
|
+
when 21
|
163
|
+
@cpu = :ppc64
|
164
|
+
when 22
|
165
|
+
@cpu = :s390
|
166
|
+
when 43
|
167
|
+
@cpu = :sparcv9
|
168
|
+
when 50
|
169
|
+
@cpu = :ia64
|
170
|
+
when 62
|
171
|
+
@cpu = :x86_64
|
172
|
+
else
|
173
|
+
raise "Invalid ELF archtype: #{archtype}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# PE/COFF format
|
178
|
+
def read_pe(f)
|
179
|
+
# 0-1 "MZ"
|
180
|
+
@file_format = :pe
|
181
|
+
# 60-63
|
182
|
+
f.seek(60, IO::SEEK_SET)
|
183
|
+
pe_offset = f.read(4).unpack('V')[0]
|
184
|
+
# read PE signature
|
185
|
+
f.seek(pe_offset)
|
186
|
+
raise 'invalid pe format' if f.read(4) != "PE\000\000"
|
187
|
+
# read COFF header
|
188
|
+
case machine = f.read(2).unpack('v')[0]
|
189
|
+
when 0x014c
|
190
|
+
@cpu = :i386
|
191
|
+
@endian = :little
|
192
|
+
@bits = 32
|
193
|
+
when 0x0200
|
194
|
+
@cpu = :ia64
|
195
|
+
@endian = :little
|
196
|
+
@bits = 64
|
197
|
+
when 0x8664
|
198
|
+
@cpu = :x86_64
|
199
|
+
@endian = :little
|
200
|
+
@bits = 64
|
201
|
+
else
|
202
|
+
raise "Invalid coff machine: #{machine}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class OraConf
|
208
|
+
include MiniRegistry
|
209
|
+
|
210
|
+
attr_reader :cc_is_gcc
|
211
|
+
attr_reader :version
|
212
|
+
attr_reader :cflags
|
213
|
+
attr_reader :libs
|
214
|
+
|
215
|
+
def initialize
|
216
|
+
raise 'use OraConf.get instead'
|
217
|
+
end
|
218
|
+
|
219
|
+
def self.get
|
220
|
+
original_CFLAGS = $CFLAGS
|
221
|
+
original_defs = $defs
|
222
|
+
ic_dir = nil
|
223
|
+
begin
|
224
|
+
# check Oracle instant client
|
225
|
+
if with_config('instant-client')
|
226
|
+
puts <<EOS
|
227
|
+
=======================================================
|
228
|
+
|
229
|
+
'--with-instant-client' is an obsolete option. ignore it.
|
230
|
+
|
231
|
+
=======================================================
|
232
|
+
EOS
|
233
|
+
end
|
234
|
+
ic_dir = check_ic_dir
|
235
|
+
if ic_dir
|
236
|
+
OraConfIC.new(ic_dir)
|
237
|
+
else
|
238
|
+
OraConfFC.new()
|
239
|
+
end
|
240
|
+
rescue
|
241
|
+
case ENV['LANG']
|
242
|
+
when /^ja/
|
243
|
+
lang = 'ja'
|
244
|
+
else
|
245
|
+
lang = 'en'
|
246
|
+
end
|
247
|
+
print <<EOS
|
248
|
+
---------------------------------------------------
|
249
|
+
error messages:
|
250
|
+
#{$!.to_str}
|
251
|
+
---------------------------------------------------
|
252
|
+
See:
|
253
|
+
* http://ruby-oci8.rubyforge.org/#{lang}/HowToInstall.html
|
254
|
+
* http://ruby-oci8.rubyforge.org/#{lang}/ReportInstallProblem.html
|
255
|
+
|
256
|
+
EOS
|
257
|
+
exc = RuntimeError.new
|
258
|
+
exc.set_backtrace($!.backtrace)
|
259
|
+
raise exc
|
260
|
+
ensure
|
261
|
+
$CFLAGS = original_CFLAGS
|
262
|
+
$defs = original_defs
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
def self.ld_envs
|
267
|
+
@@ld_envs
|
268
|
+
end
|
269
|
+
|
270
|
+
private
|
271
|
+
|
272
|
+
def self.check_ic_dir
|
273
|
+
print "checking for load library path... "
|
274
|
+
STDOUT.flush
|
275
|
+
|
276
|
+
# get library load path names
|
277
|
+
oci_basename = 'libclntsh'
|
278
|
+
oci_glob_postfix = '.[0-9]*'
|
279
|
+
ocidata_basename = ['libociei', 'libociicus']
|
280
|
+
@@ld_envs = %w[LD_LIBRARY_PATH]
|
281
|
+
so_ext = 'so'
|
282
|
+
check_proc = nil
|
283
|
+
case RUBY_PLATFORM
|
284
|
+
when /mswin32|cygwin|mingw32|bccwin32/
|
285
|
+
oci_basename = 'oci'
|
286
|
+
oci_glob_postfix = ''
|
287
|
+
ocidata_basename = ['oraociei11', 'oraociicus11', 'oraociei10', 'oraociicus10']
|
288
|
+
@@ld_envs = %w[PATH]
|
289
|
+
so_ext = 'dll'
|
290
|
+
when /i.86-linux/
|
291
|
+
check_proc = Proc.new do |file|
|
292
|
+
so = MiniSOReader.new(file)
|
293
|
+
if so.cpu == :i386
|
294
|
+
true
|
295
|
+
else
|
296
|
+
puts " skip: #{file} is for #{so.cpu} cpu."
|
297
|
+
false
|
298
|
+
end
|
299
|
+
end
|
300
|
+
when /ia64-linux/
|
301
|
+
check_proc = Proc.new do |file|
|
302
|
+
so = MiniSOReader.new(file)
|
303
|
+
if so.cpu == :ia64
|
304
|
+
true
|
305
|
+
else
|
306
|
+
puts " skip: #{file} is for #{so.cpu} cpu."
|
307
|
+
false
|
308
|
+
end
|
309
|
+
end
|
310
|
+
when /x86_64-linux/
|
311
|
+
check_proc = Proc.new do |file|
|
312
|
+
so = MiniSOReader.new(file)
|
313
|
+
if so.cpu == :x86_64
|
314
|
+
true
|
315
|
+
else
|
316
|
+
puts " skip: #{file} is for #{so.cpu} cpu."
|
317
|
+
false
|
318
|
+
end
|
319
|
+
end
|
320
|
+
when /solaris/
|
321
|
+
if [0].pack('l!').length == 8
|
322
|
+
@@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH]
|
323
|
+
else
|
324
|
+
@@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH]
|
325
|
+
end
|
326
|
+
when /aix/
|
327
|
+
oci_glob_postfix = ''
|
328
|
+
@@ld_envs = %w[LIBPATH]
|
329
|
+
so_ext = 'a'
|
330
|
+
when /hppa.*-hpux/
|
331
|
+
if [0].pack('l!').length == 4
|
332
|
+
@@ld_envs = %w[SHLIB_PATH]
|
333
|
+
end
|
334
|
+
so_ext = 'sl'
|
335
|
+
when /darwin/
|
336
|
+
@@ld_envs = %w[DYLD_LIBRARY_PATH]
|
337
|
+
so_ext = 'dylib'
|
338
|
+
end
|
339
|
+
|
340
|
+
glob_name = "#{oci_basename}.#{so_ext}#{oci_glob_postfix}"
|
341
|
+
ld_path = nil
|
342
|
+
file = nil
|
343
|
+
@@ld_envs.collect do |env|
|
344
|
+
puts "(#{env})... "
|
345
|
+
ENV[env] && ENV[env].split(File::PATH_SEPARATOR)
|
346
|
+
end.flatten.each do |path|
|
347
|
+
next if path.nil? or path == ''
|
348
|
+
path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
|
349
|
+
files = Dir.glob(File.join(path, glob_name))
|
350
|
+
next if files.empty?
|
351
|
+
STDOUT.flush
|
352
|
+
next if (check_proc && !check_proc.call(files[0]))
|
353
|
+
file = files[0]
|
354
|
+
ld_path = path
|
355
|
+
break
|
356
|
+
end
|
357
|
+
|
358
|
+
if ld_path.nil? and RUBY_PLATFORM =~ /linux/
|
359
|
+
open("|/sbin/ldconfig -p") do |f|
|
360
|
+
print "(ld.so.conf)... "
|
361
|
+
STDOUT.flush
|
362
|
+
while line = f.gets
|
363
|
+
if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/
|
364
|
+
file = "#$1/libclntsh.so.#$2"
|
365
|
+
path = $1
|
366
|
+
next if (check_proc && !check_proc.call(file))
|
367
|
+
ld_path = path
|
368
|
+
break
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
if ld_path
|
375
|
+
ocidata_basename.each do |basename|
|
376
|
+
if File.exist?(File.join(ld_path, "#{basename}.#{so_ext}"))
|
377
|
+
puts " found: #{file} looks like an instant client."
|
378
|
+
return ld_path
|
379
|
+
end
|
380
|
+
end
|
381
|
+
puts " found: #{file} looks like a full client."
|
382
|
+
else
|
383
|
+
puts " not found"
|
384
|
+
end
|
385
|
+
nil
|
386
|
+
end
|
387
|
+
|
388
|
+
def init
|
389
|
+
check_cc()
|
390
|
+
@cc_is_gcc = check_cc_is_gcc()
|
391
|
+
@lp64 = check_lp64()
|
392
|
+
check_ruby_header()
|
393
|
+
end
|
394
|
+
|
395
|
+
def check_cc
|
396
|
+
print "checking for cc... "
|
397
|
+
STDOUT.flush
|
398
|
+
if try_run("int main() { return 0; }")
|
399
|
+
puts "ok"
|
400
|
+
else
|
401
|
+
puts "ng"
|
402
|
+
raise "C compiler doesn't work correctly."
|
403
|
+
end
|
404
|
+
end # check_cc
|
405
|
+
|
406
|
+
def check_cc_is_gcc
|
407
|
+
# bcc defines __GNUC__. why??
|
408
|
+
return false if RUBY_PLATFORM =~ /bccwin32/
|
409
|
+
|
410
|
+
print "checking for gcc... "
|
411
|
+
STDOUT.flush
|
412
|
+
if macro_defined?("__GNUC__", "")
|
413
|
+
print "yes\n"
|
414
|
+
return true
|
415
|
+
else
|
416
|
+
print "no\n"
|
417
|
+
return false
|
418
|
+
end
|
419
|
+
end # check_cc_is_gcc
|
420
|
+
|
421
|
+
def check_lp64
|
422
|
+
print "checking for LP64... "
|
423
|
+
STDOUT.flush
|
424
|
+
if try_run("int main() { return sizeof(long) == 8 ? 0 : 1; }")
|
425
|
+
puts "yes"
|
426
|
+
true
|
427
|
+
else
|
428
|
+
puts "no"
|
429
|
+
false
|
430
|
+
end
|
431
|
+
end # check_lp64
|
432
|
+
|
433
|
+
def check_ruby_header
|
434
|
+
print "checking for ruby header... "
|
435
|
+
STDOUT.flush
|
436
|
+
unless File.exist?("#{Config::CONFIG['archdir']}/ruby.h")
|
437
|
+
puts "ng"
|
438
|
+
if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{Config::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
|
439
|
+
raise <<EOS
|
440
|
+
#{Config::CONFIG['archdir']}/ruby.h doesn't exist.
|
441
|
+
Run the following commands to fix the problem.
|
442
|
+
|
443
|
+
cd #{Config::CONFIG['archdir']}
|
444
|
+
sudo ln -s ../universal-darwin8.0/* ./
|
445
|
+
EOS
|
446
|
+
else
|
447
|
+
raise <<EOS
|
448
|
+
#{Config::CONFIG['archdir']}/ruby.h doesn't exist.
|
449
|
+
Install the ruby development library.
|
450
|
+
EOS
|
451
|
+
end
|
452
|
+
end
|
453
|
+
if RUBY_PLATFORM =~ /linux/ and not File.exist?("/usr/include/sys/types.h")
|
454
|
+
raise <<EOS
|
455
|
+
Do you install glibc-devel(redhat) or libc6-dev(debian)?
|
456
|
+
You need /usr/include/sys/types.h to compile ruby-oci8.
|
457
|
+
EOS
|
458
|
+
end
|
459
|
+
puts "ok"
|
460
|
+
end # check_ruby_header
|
461
|
+
|
462
|
+
def try_link_oci
|
463
|
+
original_libs = $libs
|
464
|
+
begin
|
465
|
+
$libs += " -L#{CONFIG['libdir']} " + @libs
|
466
|
+
have_func("OCIInitialize", "oci.h")
|
467
|
+
ensure
|
468
|
+
$libs = original_libs
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
473
|
+
|
474
|
+
def get_libs(base_dir = oci_base_dir)
|
475
|
+
case RUBY_PLATFORM
|
476
|
+
when /cygwin/
|
477
|
+
open("OCI.def", "w") do |f|
|
478
|
+
f.puts("EXPORTS")
|
479
|
+
open("|nm #{base_dir}/LIB/MSVC/OCI.LIB") do |r|
|
480
|
+
while line = r.gets
|
481
|
+
f.puts($') if line =~ / T _/
|
482
|
+
end
|
483
|
+
end
|
484
|
+
end
|
485
|
+
command = "dlltool -d OCI.def -D OCI.DLL -l libOCI.a"
|
486
|
+
print("Running: '#{command}' ...")
|
487
|
+
STDOUT.flush
|
488
|
+
system(command)
|
489
|
+
puts("done")
|
490
|
+
"-L. -lOCI"
|
491
|
+
when /bccwin32/
|
492
|
+
# replace '/' to '\\' because bcc linker misunderstands
|
493
|
+
# 'C:/foo/bar/OCI.LIB' as unknown option.
|
494
|
+
lib = "#{base_dir}/LIB/BORLAND/OCI.LIB"
|
495
|
+
return lib.tr('/', '\\') if File.exist?(lib)
|
496
|
+
raise <<EOS
|
497
|
+
#{lib} does not exist.
|
498
|
+
|
499
|
+
Your Oracle may not support Borland C++.
|
500
|
+
If you want to run this module, run the following command at your own risk.
|
501
|
+
cd #{base_dir.tr('/', '\\')}\\LIB
|
502
|
+
mkdir Borland
|
503
|
+
cd Borland
|
504
|
+
coff2omf ..\\MSVC\\OCI.LIB OCI.LIB
|
505
|
+
EOS
|
506
|
+
exit 1
|
507
|
+
else
|
508
|
+
"\"#{base_dir}/LIB/MSVC/OCI.LIB\""
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
# OraConf for Full Client
|
516
|
+
class OraConfFC < OraConf
|
517
|
+
def initialize
|
518
|
+
init
|
519
|
+
|
520
|
+
@oracle_home = get_home()
|
521
|
+
if RUBY_PLATFORM =~ /freebsd/ && @oracle_home == '/usr/local/oracle8-client'
|
522
|
+
@version = '817'
|
523
|
+
else
|
524
|
+
@version = get_version()
|
525
|
+
end
|
526
|
+
@cflags = get_cflags()
|
527
|
+
$CFLAGS += @cflags
|
528
|
+
|
529
|
+
if !@lp64 && File.exist?("#{@oracle_home}/lib32")
|
530
|
+
# ruby - 32bit
|
531
|
+
# oracle - 64bit
|
532
|
+
use_lib32 = true
|
533
|
+
else
|
534
|
+
use_lib32 = false
|
535
|
+
end
|
536
|
+
|
537
|
+
# default
|
538
|
+
if @version.to_i >= 900
|
539
|
+
if use_lib32
|
540
|
+
lib_dir = "#{@oracle_home}/lib32"
|
541
|
+
else
|
542
|
+
lib_dir = "#{@oracle_home}/lib"
|
543
|
+
end
|
544
|
+
case RUBY_PLATFORM
|
545
|
+
when /solaris/
|
546
|
+
@libs = " -L#{lib_dir} -R#{lib_dir} -lclntsh"
|
547
|
+
when /linux/
|
548
|
+
@libs = " -L#{lib_dir} -Wl,-rpath,#{lib_dir} -lclntsh"
|
549
|
+
else
|
550
|
+
@libs = " -L#{lib_dir} -lclntsh"
|
551
|
+
end
|
552
|
+
return if try_link_oci()
|
553
|
+
end
|
554
|
+
|
555
|
+
# get from demo_rdbms.mk
|
556
|
+
if use_lib32
|
557
|
+
if File.exist?("#{@oracle_home}/rdbms/demo/demo_rdbms32.mk")
|
558
|
+
@libs = get_libs('32', '')
|
559
|
+
else
|
560
|
+
@libs = get_libs('', '32')
|
561
|
+
end
|
562
|
+
else
|
563
|
+
@libs = get_libs()
|
564
|
+
end
|
565
|
+
return if try_link_oci()
|
566
|
+
|
567
|
+
raise 'cannot compile OCI'
|
568
|
+
end
|
569
|
+
|
570
|
+
private
|
571
|
+
|
572
|
+
def get_version
|
573
|
+
print("Get the version of Oracle from SQL*Plus... ")
|
574
|
+
STDOUT.flush
|
575
|
+
version = nil
|
576
|
+
dev_null = RUBY_PLATFORM =~ /mswin32|mingw32|bccwin32/ ? "nul" : "/dev/null"
|
577
|
+
if File.exist?("#{@oracle_home}/bin/plus80.exe")
|
578
|
+
sqlplus = "plus80.exe"
|
579
|
+
else
|
580
|
+
sqlplus = "sqlplus"
|
581
|
+
end
|
582
|
+
Logging::open do
|
583
|
+
open("|#{@oracle_home}/bin/#{sqlplus} < #{dev_null}") do |f|
|
584
|
+
while line = f.gets
|
585
|
+
print line
|
586
|
+
if line =~ /(\d+)\.(\d)\.(\d)/
|
587
|
+
version = $1 + $2 + $3
|
588
|
+
break
|
589
|
+
end
|
590
|
+
end
|
591
|
+
end
|
592
|
+
end
|
593
|
+
if version.nil?
|
594
|
+
raise 'cannot get Oracle version from sqlplus'
|
595
|
+
end
|
596
|
+
puts version
|
597
|
+
version
|
598
|
+
end # get_version
|
599
|
+
|
600
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
601
|
+
|
602
|
+
def is_valid_home?(oracle_home)
|
603
|
+
return false if oracle_home.nil?
|
604
|
+
sqlplus = "#{oracle_home}/bin/sqlplus.exe"
|
605
|
+
print("checking for ORACLE_HOME(#{oracle_home})... ")
|
606
|
+
STDOUT.flush
|
607
|
+
if File.exist?(sqlplus)
|
608
|
+
puts("yes")
|
609
|
+
true
|
610
|
+
else
|
611
|
+
puts("no")
|
612
|
+
false
|
613
|
+
end
|
614
|
+
end
|
615
|
+
|
616
|
+
def get_home()
|
617
|
+
oracle_home = ENV['ORACLE_HOME']
|
618
|
+
if oracle_home.nil?
|
619
|
+
struct = Struct.new("OracleHome", :name, :path)
|
620
|
+
oracle_homes = []
|
621
|
+
begin
|
622
|
+
last_home = get_local_registry("SOFTWARE\\ORACLE\\ALL_HOMES", 'LAST_HOME')
|
623
|
+
0.upto last_home.to_i do |id|
|
624
|
+
oracle_homes << "HOME#{id}"
|
625
|
+
end
|
626
|
+
rescue MiniRegistryError
|
627
|
+
end
|
628
|
+
oracle_homes << "KEY_XE"
|
629
|
+
oracle_homes << "KEY_XEClient"
|
630
|
+
oracle_homes.collect! do |home|
|
631
|
+
begin
|
632
|
+
name = get_local_registry("SOFTWARE\\ORACLE\\#{home}", 'ORACLE_HOME_NAME')
|
633
|
+
path = get_local_registry("SOFTWARE\\ORACLE\\#{home}", 'ORACLE_HOME')
|
634
|
+
path.chomp!("\\")
|
635
|
+
struct.new(name, path) if is_valid_home?(path)
|
636
|
+
rescue MiniRegistryError
|
637
|
+
nil
|
638
|
+
end
|
639
|
+
end
|
640
|
+
oracle_homes.compact!
|
641
|
+
if oracle_homes.empty?
|
642
|
+
raise <<EOS
|
643
|
+
Set the environment variable ORACLE_HOME if Oracle Full Client.
|
644
|
+
Append the path of Oracle client libraries to #{OraConf.ld_envs[0]} if Oracle Instant Client.
|
645
|
+
EOS
|
646
|
+
end
|
647
|
+
if oracle_homes.length == 1
|
648
|
+
oracle_home = oracle_homes[0].path
|
649
|
+
else
|
650
|
+
default_path = ''
|
651
|
+
if RUBY_PLATFORM =~ /cygwin/
|
652
|
+
path_sep = ':'
|
653
|
+
dir_sep = '/'
|
654
|
+
else
|
655
|
+
path_sep = ';'
|
656
|
+
dir_sep = '\\'
|
657
|
+
end
|
658
|
+
ENV['PATH'].split(path_sep).each do |path|
|
659
|
+
path.chomp!(dir_sep)
|
660
|
+
if File.exist?("#{path}/OCI.DLL")
|
661
|
+
default_path = path
|
662
|
+
break
|
663
|
+
end
|
664
|
+
end
|
665
|
+
puts "---------------------------------------------------"
|
666
|
+
puts "Multiple Oracle Homes are found."
|
667
|
+
printf " %-15s : %s\n", "[NAME]", "[PATH]"
|
668
|
+
oracle_homes.each do |home|
|
669
|
+
if RUBY_PLATFORM =~ /cygwin/
|
670
|
+
path = `cygpath -u '#{home.path}'`.chomp!
|
671
|
+
else
|
672
|
+
path = home.path
|
673
|
+
end
|
674
|
+
if default_path.downcase == "#{path.downcase}#{dir_sep}bin"
|
675
|
+
oracle_home = home
|
676
|
+
end
|
677
|
+
printf " %-15s : %s\n", home.name, home.path
|
678
|
+
end
|
679
|
+
if oracle_home.nil?
|
680
|
+
puts "default oracle home is not found."
|
681
|
+
puts "---------------------------------------------------"
|
682
|
+
raise 'Cannot get ORACLE_HOME. Please set the environment valiable ORACLE_HOME.'
|
683
|
+
else
|
684
|
+
printf "use %s\n", oracle_home.name
|
685
|
+
puts "run ohsel.exe to use another oracle home."
|
686
|
+
puts "---------------------------------------------------"
|
687
|
+
oracle_home = oracle_home.path
|
688
|
+
end
|
689
|
+
end
|
690
|
+
end
|
691
|
+
if RUBY_PLATFORM =~ /cygwin/
|
692
|
+
oracle_home = oracle_home.sub(/^([a-zA-Z]):/, "/cygdrive/\\1")
|
693
|
+
end
|
694
|
+
oracle_home.gsub(/\\/, '/')
|
695
|
+
end
|
696
|
+
|
697
|
+
def oci_base_dir
|
698
|
+
case @version
|
699
|
+
when /80./
|
700
|
+
"#{@oracle_home}/OCI80"
|
701
|
+
else
|
702
|
+
"#{@oracle_home}/OCI"
|
703
|
+
end
|
704
|
+
end
|
705
|
+
|
706
|
+
def get_cflags
|
707
|
+
unless File.exist?("#{oci_base_dir}/INCLUDE/OCI.H")
|
708
|
+
raise "'#{oci_base_dir}/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
|
709
|
+
end
|
710
|
+
if RUBY_PLATFORM =~ /cygwin/
|
711
|
+
" \"-I#{oci_base_dir}/INCLUDE\" -D_int64=\"long long\""
|
712
|
+
else
|
713
|
+
" \"-I#{oci_base_dir}/INCLUDE\""
|
714
|
+
end
|
715
|
+
end
|
716
|
+
|
717
|
+
else # when UNIX
|
718
|
+
|
719
|
+
def get_home
|
720
|
+
oracle_home = ENV['ORACLE_HOME']
|
721
|
+
if oracle_home.nil?
|
722
|
+
raise <<EOS
|
723
|
+
Set the environment variable ORACLE_HOME if Oracle Full Client.
|
724
|
+
Append the path of Oracle client libraries to #{OraConf.ld_envs[0]} if Oracle Instant Client.
|
725
|
+
EOS
|
726
|
+
end
|
727
|
+
oracle_home
|
728
|
+
end
|
729
|
+
|
730
|
+
def get_cflags
|
731
|
+
cflags = ''
|
732
|
+
ok = false
|
733
|
+
original_CFLAGS = $CFLAGS
|
734
|
+
begin
|
735
|
+
for i in ["rdbms/public", "rdbms/demo", "network/public", "plsql/public"]
|
736
|
+
cflags += " -I#{@oracle_home}/#{i}"
|
737
|
+
$CFLAGS += " -I#{@oracle_home}/#{i}"
|
738
|
+
print("try #{cflags}\n");
|
739
|
+
if have_header("oci.h")
|
740
|
+
ok = true
|
741
|
+
break
|
742
|
+
end
|
743
|
+
end
|
744
|
+
unless ok
|
745
|
+
if @version.to_i >= 1000
|
746
|
+
oci_h = "#{@oracle_home}/rdbms/public/oci.h"
|
747
|
+
else
|
748
|
+
oci_h = "#{@oracle_home}/rdbms/demo/oci.h"
|
749
|
+
end
|
750
|
+
unless File.exist?(oci_h)
|
751
|
+
raise "'#{oci_h}' does not exists. Install 'Oracle Call Interface' component."
|
752
|
+
end
|
753
|
+
raise 'Cannot get proper cflags.'
|
754
|
+
end
|
755
|
+
cflags
|
756
|
+
ensure
|
757
|
+
$CFLAGS = original_CFLAGS
|
758
|
+
end
|
759
|
+
end # get_cflags
|
760
|
+
|
761
|
+
def get_libs(postfix1 = '', postfix2 = "")
|
762
|
+
print("Running make for $ORACLE_HOME/rdbms/demo/demo_rdbms#{postfix1}.mk (build#{postfix2}) ...")
|
763
|
+
STDOUT.flush
|
764
|
+
|
765
|
+
make_opt = "CC='echo MARKER' EXE=/dev/null ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh'"
|
766
|
+
if @cc_is_gcc && /solaris/ =~ RUBY_PLATFORM
|
767
|
+
# suggested by Brian Candler.
|
768
|
+
make_opt += " KPIC_OPTION= NOKPIC_CCFLAGS#{postfix2}="
|
769
|
+
end
|
770
|
+
|
771
|
+
command = "|make -f #{@oracle_home}/rdbms/demo/demo_rdbms#{postfix1}.mk build#{postfix2} #{make_opt}"
|
772
|
+
marker = /^\s*MARKER/
|
773
|
+
echo = /^\s*echo/
|
774
|
+
libs = nil
|
775
|
+
Logging::open do
|
776
|
+
puts command
|
777
|
+
open(command, "r") do |f|
|
778
|
+
while line = f.gets
|
779
|
+
puts line
|
780
|
+
line.chomp!
|
781
|
+
line = $' while line =~ echo
|
782
|
+
if line =~ marker
|
783
|
+
# found a line where a compiler runs.
|
784
|
+
libs = $'
|
785
|
+
libs.gsub!(/-o\s+\/dev\/null/, "")
|
786
|
+
libs.gsub!(/-o\s+build/, "")
|
787
|
+
end
|
788
|
+
end
|
789
|
+
end
|
790
|
+
end
|
791
|
+
raise 'Cannot get proper libs.' if libs.nil?
|
792
|
+
print("OK\n")
|
793
|
+
|
794
|
+
case RUBY_PLATFORM
|
795
|
+
when /hpux/
|
796
|
+
if @cc_is_gcc
|
797
|
+
# strip +DA2.0W, +DS2.0, -Wl,+s, -Wl,+n
|
798
|
+
libs.gsub!(/\+DA\S+(\s)*/, "")
|
799
|
+
libs.gsub!(/\+DS\S+(\s)*/, "")
|
800
|
+
libs.gsub!(/-Wl,\+[sn](\s)*/, "")
|
801
|
+
end
|
802
|
+
libs.gsub!(/ -Wl,/, " ")
|
803
|
+
when /aix/
|
804
|
+
if @cc_is_gcc
|
805
|
+
# strip -bI:/xxx
|
806
|
+
libs.gsub!(/(-bI:\S+)/, '')
|
807
|
+
end
|
808
|
+
end
|
809
|
+
|
810
|
+
# remove object files from libs.
|
811
|
+
objs = []
|
812
|
+
libs.gsub!(/\S+\.o\b/) do |obj|
|
813
|
+
objs << obj
|
814
|
+
""
|
815
|
+
end
|
816
|
+
# change object files to an archive file to work around.
|
817
|
+
if objs.length > 0
|
818
|
+
Logging::open do
|
819
|
+
puts "change object files to an archive file."
|
820
|
+
command = Config::CONFIG["AR"] + " cru oracle_objs.a " + objs.join(" ")
|
821
|
+
puts command
|
822
|
+
system(command)
|
823
|
+
libs = "oracle_objs.a " + libs
|
824
|
+
end
|
825
|
+
end
|
826
|
+
libs
|
827
|
+
end # get_libs
|
828
|
+
end
|
829
|
+
end
|
830
|
+
|
831
|
+
# OraConf for Instant Client
|
832
|
+
class OraConfIC < OraConf
|
833
|
+
def initialize(ic_dir)
|
834
|
+
init
|
835
|
+
|
836
|
+
if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+\.\d+\.\d+\.\d+)\/client(64)?\/lib(?:64)?/
|
837
|
+
# rpm package
|
838
|
+
# official x86 rpms:
|
839
|
+
# library: /usr/lib/oracle/X.X.X.X/client/lib/
|
840
|
+
# include: /usr/include/oracle/X.X.X.X/client/
|
841
|
+
#
|
842
|
+
# official x86_64 rpms:
|
843
|
+
# library: /usr/lib/oracle/X.X.X.X/client64/lib/
|
844
|
+
# include: /usr/include/oracle/X.X.X.X/client64/
|
845
|
+
#
|
846
|
+
# third-party x86_64 rpms(*1):
|
847
|
+
# library: /usr/lib64/oracle/X.X.X.X/client/lib/
|
848
|
+
# or /usr/lib64/oracle/X.X.X.X/client/lib64/
|
849
|
+
# include: /usr/include/oracle/X.X.X.X/client/
|
850
|
+
#
|
851
|
+
# *1 These had been used before Oracle released official x86_64 rpms.
|
852
|
+
#
|
853
|
+
lib_dir = ic_dir
|
854
|
+
inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
|
855
|
+
else
|
856
|
+
# zip package
|
857
|
+
lib_dir = ic_dir
|
858
|
+
inc_dir = "#{ic_dir}/sdk/include"
|
859
|
+
end
|
860
|
+
|
861
|
+
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
|
862
|
+
unless File.exist?("#{ic_dir}/sdk/lib/msvc/oci.lib")
|
863
|
+
raise <<EOS
|
864
|
+
Could not compile with Oracle instant client.
|
865
|
+
#{ic_dir}/sdk/lib/msvc/oci.lib could not be found.
|
866
|
+
EOS
|
867
|
+
raise 'failed'
|
868
|
+
end
|
869
|
+
@cflags = " \"-I#{inc_dir}\""
|
870
|
+
@cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin/
|
871
|
+
@libs = get_libs("#{ic_dir}/sdk")
|
872
|
+
ld_path = nil
|
873
|
+
else
|
874
|
+
@cflags = " -I#{inc_dir}"
|
875
|
+
# set ld_path and so_ext
|
876
|
+
case RUBY_PLATFORM
|
877
|
+
when /aix/
|
878
|
+
ld_path = 'LIBPATH'
|
879
|
+
so_ext = 'a'
|
880
|
+
when /hppa.*-hpux/
|
881
|
+
if @lp64
|
882
|
+
ld_path = 'LD_LIBRARY_PATH'
|
883
|
+
else
|
884
|
+
ld_path = 'SHLIB_PATH'
|
885
|
+
end
|
886
|
+
so_ext = 'sl'
|
887
|
+
when /darwin/
|
888
|
+
ld_path = 'DYLD_LIBRARY_PATH'
|
889
|
+
so_ext = 'dylib'
|
890
|
+
else
|
891
|
+
ld_path = 'LD_LIBRARY_PATH'
|
892
|
+
so_ext = 'so'
|
893
|
+
end
|
894
|
+
# check Oracle client library.
|
895
|
+
unless File.exist?("#{lib_dir}/libclntsh.#{so_ext}")
|
896
|
+
files = Dir.glob("#{lib_dir}/libclntsh.#{so_ext}.*")
|
897
|
+
if files.empty?
|
898
|
+
raise <<EOS
|
899
|
+
Could not compile with Oracle instant client.
|
900
|
+
'#{lib_dir}/libclntsh.#{so_ext}' could not be found.
|
901
|
+
Did you install instantclient-basic?
|
902
|
+
EOS
|
903
|
+
else
|
904
|
+
file = File.basename(files.sort[-1])
|
905
|
+
raise <<EOS
|
906
|
+
Could not compile with Oracle instant client.
|
907
|
+
#{lib_dir}/libclntsh.#{so_ext} could not be found.
|
908
|
+
You may need to make a symbolic link.
|
909
|
+
cd #{lib_dir}
|
910
|
+
ln -s #{file} libclntsh.#{so_ext}
|
911
|
+
EOS
|
912
|
+
end
|
913
|
+
raise 'failed'
|
914
|
+
end
|
915
|
+
@libs = " -L#{lib_dir} -lclntsh "
|
916
|
+
end
|
917
|
+
unless File.exist?("#{inc_dir}/oci.h")
|
918
|
+
raise <<EOS
|
919
|
+
'#{inc_dir}/oci.h' does not exist.
|
920
|
+
Install 'Instant Client SDK'.
|
921
|
+
EOS
|
922
|
+
end
|
923
|
+
$CFLAGS += @cflags
|
924
|
+
if try_link_oci()
|
925
|
+
major = try_constant("OCI_MAJOR_VERSION", "oci.h")
|
926
|
+
minor = try_constant("OCI_MINOR_VERSION", "oci.h")
|
927
|
+
if major and minor
|
928
|
+
@version = format('%d%d0', major, minor)
|
929
|
+
else
|
930
|
+
# 10.1.0 doesn't have OCI_MAJOR_VERSION and OCI_MINOR_VERSION in oci.h.
|
931
|
+
@version = "1010"
|
932
|
+
end
|
933
|
+
return
|
934
|
+
end
|
935
|
+
|
936
|
+
if RUBY_PLATFORM =~ /darwin/
|
937
|
+
is_intelmac = ([1].pack('s') == "\001\000")
|
938
|
+
arch_ppc_error = false
|
939
|
+
arch_i386_error = false
|
940
|
+
open('mkmf.log', 'r') do |f|
|
941
|
+
while line = f.gets
|
942
|
+
# universal-darwin8.0 (Mac OS X 10.4?)
|
943
|
+
if line.include? 'cputype (18, architecture ppc) does not match cputype (7)'
|
944
|
+
# try to link an i386 library but the instant client is ppc.
|
945
|
+
arch_i386_error = true
|
946
|
+
end
|
947
|
+
if line.include? 'cputype (7, architecture i386) does not match cputype (18)'
|
948
|
+
# try to link a ppc library but the instant client is i386.
|
949
|
+
arch_ppc_error = true
|
950
|
+
end
|
951
|
+
if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
|
952
|
+
raise <<EOS
|
953
|
+
Intel mac instant client is for Mac OS X 10.5.
|
954
|
+
It doesn't work on Mac OS X 10.4 or before.
|
955
|
+
|
956
|
+
You have three workarounds.
|
957
|
+
1. Compile ruby as ppc binary and use it with ppc instant client.
|
958
|
+
2. Use JRuby and JDBC
|
959
|
+
3. Use a third-party ODBC driver and ruby-odbc.
|
960
|
+
EOS
|
961
|
+
# '
|
962
|
+
end
|
963
|
+
# universal-darwin9.0 (Mac OS X 10.5?)
|
964
|
+
if line.include? 'Undefined symbols for architecture i386:'
|
965
|
+
# try to link an i386 library but the instant client is ppc.
|
966
|
+
arch_i386_error = true
|
967
|
+
end
|
968
|
+
if line.include? 'Undefined symbols for architecture ppc:'
|
969
|
+
# try to link a ppc library but the instant client is i386.
|
970
|
+
arch_ppc_error = true
|
971
|
+
end
|
972
|
+
|
973
|
+
if arch_i386_error
|
974
|
+
if is_intelmac
|
975
|
+
# intel mac and '-arch i386' error
|
976
|
+
raise <<EOS
|
977
|
+
Could not compile with Oracle instant client.
|
978
|
+
Use intel mac instant client.
|
979
|
+
EOS
|
980
|
+
else
|
981
|
+
# ppc mac and '-arch i386' error
|
982
|
+
raise <<EOS
|
983
|
+
Could not compile with Oracle instant client.
|
984
|
+
You may need to set a environment variable:
|
985
|
+
RC_ARCHS=ppc
|
986
|
+
export RC_ARCHS
|
987
|
+
If it does not fix the problem, delete all '-arch i386'
|
988
|
+
in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
|
989
|
+
EOS
|
990
|
+
end
|
991
|
+
end
|
992
|
+
|
993
|
+
if arch_ppc_error
|
994
|
+
if is_intelmac
|
995
|
+
# intel mac and '-arch ppc' error
|
996
|
+
raise <<EOS
|
997
|
+
Could not compile with Oracle instant client.
|
998
|
+
You may need to set a environment variable:
|
999
|
+
RC_ARCHS=i386
|
1000
|
+
export RC_ARCHS
|
1001
|
+
If it does not fix the problem, delete all '-arch ppc'
|
1002
|
+
in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
|
1003
|
+
EOS
|
1004
|
+
else
|
1005
|
+
# ppc mac and '-arch ppc' error
|
1006
|
+
raise <<EOS
|
1007
|
+
Could not compile with Oracle instant client.
|
1008
|
+
Use ppc instant client.
|
1009
|
+
EOS
|
1010
|
+
end
|
1011
|
+
end
|
1012
|
+
end
|
1013
|
+
end
|
1014
|
+
end
|
1015
|
+
|
1016
|
+
unless ld_path.nil?
|
1017
|
+
raise <<EOS
|
1018
|
+
Could not compile with Oracle instant client.
|
1019
|
+
You may need to set a environment variable:
|
1020
|
+
#{ld_path}=#{lib_dir}
|
1021
|
+
export #{ld_path}
|
1022
|
+
EOS
|
1023
|
+
end
|
1024
|
+
raise 'failed'
|
1025
|
+
end
|
1026
|
+
end
|