ruby-oci8 1.0.2
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 +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
|