ruby-oci8 1.0.7 → 2.0.0
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 +1254 -390
- data/Makefile +10 -13
- data/README +56 -385
- data/VERSION +1 -1
- data/dist-files +26 -27
- data/ext/oci8/.document +1 -0
- data/ext/oci8/MANIFEST +0 -4
- data/ext/oci8/apiwrap.c.tmpl +172 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1243 -0
- data/ext/oci8/attr.c +124 -384
- data/ext/oci8/bind.c +472 -164
- data/ext/oci8/encoding.c +196 -0
- data/ext/oci8/env.c +84 -253
- data/ext/oci8/error.c +196 -127
- data/ext/oci8/extconf.rb +82 -59
- data/ext/oci8/lob.c +710 -370
- data/ext/oci8/metadata.c +359 -0
- data/ext/oci8/object.c +622 -0
- data/ext/oci8/oci8.c +577 -161
- data/ext/oci8/oci8.h +354 -258
- data/ext/oci8/oci8lib.c +493 -0
- data/ext/oci8/ocidatetime.c +473 -0
- data/ext/oci8/ocinumber.c +1123 -24
- data/ext/oci8/oraconf.rb +72 -106
- data/ext/oci8/oradate.c +511 -321
- data/ext/oci8/stmt.c +752 -572
- data/ext/oci8/win32.c +131 -0
- data/ext/oci8/xmldb.c +383 -0
- data/lib/.document +2 -0
- data/lib/dbd/OCI8.rb +2 -17
- data/lib/oci8.rb.in +41 -1622
- data/lib/oci8/.document +5 -0
- data/lib/oci8/compat.rb +108 -0
- data/lib/oci8/datetime.rb +489 -0
- data/lib/oci8/encoding-init.rb +40 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2077 -0
- data/lib/oci8/object.rb +548 -0
- data/lib/oci8/oci8.rb +773 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/metaconfig +3 -3
- data/ruby-oci8.gemspec +5 -5
- data/setup.rb +4 -4
- data/test/config.rb +64 -84
- data/test/test_all.rb +14 -21
- data/test/test_array_dml.rb +317 -0
- data/test/test_bind_raw.rb +18 -25
- data/test/test_bind_time.rb +78 -91
- data/test/test_break.rb +37 -35
- data/test/test_clob.rb +33 -89
- data/test/test_connstr.rb +5 -4
- data/test/test_datetime.rb +469 -0
- data/test/test_dbi.rb +99 -60
- data/test/test_dbi_clob.rb +3 -8
- data/test/test_metadata.rb +65 -51
- data/test/test_oci8.rb +151 -55
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +76 -83
- data/test/test_oranumber.rb +405 -71
- data/test/test_rowid.rb +6 -11
- metadata +31 -32
- data/NEWS +0 -420
- data/ext/oci8/const.c +0 -165
- data/ext/oci8/define.c +0 -53
- data/ext/oci8/describe.c +0 -81
- data/ext/oci8/descriptor.c +0 -39
- data/ext/oci8/handle.c +0 -273
- data/ext/oci8/oranumber.c +0 -445
- data/ext/oci8/param.c +0 -37
- data/ext/oci8/server.c +0 -182
- data/ext/oci8/session.c +0 -99
- data/ext/oci8/svcctx.c +0 -238
- data/ruby-oci8.spec +0 -62
- data/support/README +0 -4
- data/support/runit/assert.rb +0 -281
- data/support/runit/cui/testrunner.rb +0 -101
- data/support/runit/error.rb +0 -4
- data/support/runit/method_mappable.rb +0 -20
- data/support/runit/robserver.rb +0 -25
- data/support/runit/setuppable.rb +0 -15
- data/support/runit/teardownable.rb +0 -16
- data/support/runit/testcase.rb +0 -113
- data/support/runit/testfailure.rb +0 -25
- data/support/runit/testresult.rb +0 -121
- data/support/runit/testsuite.rb +0 -43
- data/support/runit/version.rb +0 -3
- data/test/test_describe.rb +0 -137
data/ext/oci8/oci8lib.c
ADDED
@@ -0,0 +1,493 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "oci8.h"
|
7
|
+
|
8
|
+
#define DEBUG_CORE_FILE 1
|
9
|
+
#ifdef DEBUG_CORE_FILE
|
10
|
+
#include <signal.h>
|
11
|
+
#endif
|
12
|
+
|
13
|
+
static oci8_base_class_t oci8_base_class = {
|
14
|
+
NULL,
|
15
|
+
NULL,
|
16
|
+
sizeof(oci8_base_t),
|
17
|
+
};
|
18
|
+
|
19
|
+
ID oci8_id_new;
|
20
|
+
ID oci8_id_get;
|
21
|
+
ID oci8_id_set;
|
22
|
+
ID oci8_id_keys;
|
23
|
+
int oci8_in_finalizer = 0;
|
24
|
+
VALUE oci8_cOCIHandle;
|
25
|
+
|
26
|
+
static ID id_oci8_class;
|
27
|
+
|
28
|
+
static VALUE mOCI8BindType;
|
29
|
+
static VALUE cOCI8BindTypeBase;
|
30
|
+
|
31
|
+
static VALUE oci8_handle_initialize(VALUE self)
|
32
|
+
{
|
33
|
+
rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(CLASS_OF(self)));
|
34
|
+
}
|
35
|
+
|
36
|
+
void oci8_base_free(oci8_base_t *base)
|
37
|
+
{
|
38
|
+
while (base->children != NULL) {
|
39
|
+
oci8_base_free(base->children);
|
40
|
+
}
|
41
|
+
oci8_unlink_from_parent(base);
|
42
|
+
if (base->klass->free != NULL)
|
43
|
+
base->klass->free(base);
|
44
|
+
if (base->type >= OCI_DTYPE_FIRST)
|
45
|
+
OCIDescriptorFree(base->hp.ptr, base->type);
|
46
|
+
else if (base->type >= OCI_HTYPE_FIRST)
|
47
|
+
OCIHandleFree(base->hp.ptr, base->type);
|
48
|
+
base->type = 0;
|
49
|
+
base->hp.ptr = NULL;
|
50
|
+
}
|
51
|
+
|
52
|
+
static VALUE oci8_handle_free(VALUE self)
|
53
|
+
{
|
54
|
+
oci8_base_t *base = DATA_PTR(self);
|
55
|
+
|
56
|
+
oci8_base_free(base);
|
57
|
+
return self;
|
58
|
+
}
|
59
|
+
|
60
|
+
static void oci8_handle_mark(oci8_base_t *base)
|
61
|
+
{
|
62
|
+
if (base->klass->mark != NULL)
|
63
|
+
base->klass->mark(base);
|
64
|
+
}
|
65
|
+
|
66
|
+
static void oci8_handle_cleanup(oci8_base_t *base)
|
67
|
+
{
|
68
|
+
oci8_base_free(base);
|
69
|
+
free(base);
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE oci8_s_allocate(VALUE klass)
|
73
|
+
{
|
74
|
+
oci8_base_t *base;
|
75
|
+
const oci8_base_class_t *base_class;
|
76
|
+
VALUE superklass;
|
77
|
+
VALUE obj;
|
78
|
+
|
79
|
+
superklass = klass;
|
80
|
+
while (!RTEST(rb_ivar_defined(superklass, id_oci8_class))) {
|
81
|
+
superklass = RCLASS_SUPER(superklass);
|
82
|
+
if (superklass == rb_cObject)
|
83
|
+
rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass));
|
84
|
+
}
|
85
|
+
obj = rb_ivar_get(superklass, id_oci8_class);
|
86
|
+
base_class = DATA_PTR(obj);
|
87
|
+
|
88
|
+
base = xmalloc(base_class->size);
|
89
|
+
memset(base, 0, base_class->size);
|
90
|
+
|
91
|
+
obj = Data_Wrap_Struct(klass, oci8_handle_mark, oci8_handle_cleanup, base);
|
92
|
+
base->self = obj;
|
93
|
+
base->klass = base_class;
|
94
|
+
base->parent = NULL;
|
95
|
+
base->next = base;
|
96
|
+
base->prev = base;
|
97
|
+
base->children = NULL;
|
98
|
+
return obj;
|
99
|
+
}
|
100
|
+
|
101
|
+
static void at_exit_func(VALUE val)
|
102
|
+
{
|
103
|
+
oci8_in_finalizer = 1;
|
104
|
+
}
|
105
|
+
|
106
|
+
void
|
107
|
+
Init_oci8lib()
|
108
|
+
{
|
109
|
+
VALUE cOCI8;
|
110
|
+
VALUE obj;
|
111
|
+
|
112
|
+
#ifdef RUNTIME_API_CHECK
|
113
|
+
Init_oci8_apiwrap();
|
114
|
+
if (have_OCIClientVersion) {
|
115
|
+
sword major, minor, update, patch, port_update;
|
116
|
+
OCIClientVersion(&major, &minor, &update, &patch, &port_update);
|
117
|
+
oracle_client_version = ORAVERNUM(major, minor, update, patch, port_update);
|
118
|
+
}
|
119
|
+
#endif
|
120
|
+
|
121
|
+
id_oci8_class = rb_intern("__oci8_class__");
|
122
|
+
oci8_id_new = rb_intern("new");
|
123
|
+
oci8_id_get = rb_intern("get");
|
124
|
+
oci8_id_set = rb_intern("set");
|
125
|
+
oci8_id_keys = rb_intern("keys");
|
126
|
+
rb_set_end_proc(at_exit_func, Qnil);
|
127
|
+
|
128
|
+
Init_oci8_error();
|
129
|
+
Init_oci8_env();
|
130
|
+
|
131
|
+
/* OCIHandle class */
|
132
|
+
oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
|
133
|
+
rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate);
|
134
|
+
rb_define_method(oci8_cOCIHandle, "initialize", oci8_handle_initialize, 0);
|
135
|
+
rb_define_method(oci8_cOCIHandle, "free", oci8_handle_free, 0);
|
136
|
+
obj = Data_Wrap_Struct(rb_cObject, 0, 0, &oci8_base_class);
|
137
|
+
rb_ivar_set(oci8_cOCIHandle, id_oci8_class, obj);
|
138
|
+
|
139
|
+
/* OCI8 class */
|
140
|
+
cOCI8 = Init_oci8();
|
141
|
+
/* OCI8::BindType module */
|
142
|
+
mOCI8BindType = rb_define_module_under(cOCI8, "BindType");
|
143
|
+
/* OCI8::BindType::Base class */
|
144
|
+
cOCI8BindTypeBase = rb_define_class_under(mOCI8BindType, "Base", oci8_cOCIHandle);
|
145
|
+
|
146
|
+
/* Handle */
|
147
|
+
Init_oci8_bind(cOCI8BindTypeBase);
|
148
|
+
Init_oci8_stmt(cOCI8);
|
149
|
+
|
150
|
+
/* Encoding */
|
151
|
+
Init_oci8_encoding(cOCI8);
|
152
|
+
|
153
|
+
/* register allocators */
|
154
|
+
Init_oci8_metadata(cOCI8);
|
155
|
+
Init_oci8_lob(cOCI8);
|
156
|
+
|
157
|
+
Init_ora_date();
|
158
|
+
Init_oci_number(cOCI8);
|
159
|
+
Init_oci_datetime();
|
160
|
+
Init_oci_object(cOCI8);
|
161
|
+
Init_oci_xmldb();
|
162
|
+
|
163
|
+
#ifdef USE_WIN32_C
|
164
|
+
Init_oci8_win32(cOCI8);
|
165
|
+
#endif
|
166
|
+
|
167
|
+
#ifdef DEBUG_CORE_FILE
|
168
|
+
signal(SIGSEGV, SIG_DFL);
|
169
|
+
#endif
|
170
|
+
}
|
171
|
+
|
172
|
+
VALUE oci8_define_class(const char *name, oci8_base_class_t *base_class)
|
173
|
+
{
|
174
|
+
VALUE klass = rb_define_class(name, oci8_cOCIHandle);
|
175
|
+
VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class);
|
176
|
+
rb_ivar_set(klass, id_oci8_class, obj);
|
177
|
+
return klass;
|
178
|
+
}
|
179
|
+
|
180
|
+
VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_class_t *base_class)
|
181
|
+
{
|
182
|
+
VALUE klass = rb_define_class_under(outer, name, oci8_cOCIHandle);
|
183
|
+
VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, base_class);
|
184
|
+
rb_ivar_set(klass, id_oci8_class, obj);
|
185
|
+
return klass;
|
186
|
+
}
|
187
|
+
|
188
|
+
VALUE oci8_define_bind_class(const char *name, const oci8_bind_class_t *bind_class)
|
189
|
+
{
|
190
|
+
VALUE klass = rb_define_class_under(mOCI8BindType, name, cOCI8BindTypeBase);
|
191
|
+
VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)bind_class);
|
192
|
+
rb_ivar_set(klass, id_oci8_class, obj);
|
193
|
+
return klass;
|
194
|
+
}
|
195
|
+
|
196
|
+
void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent)
|
197
|
+
{
|
198
|
+
if (base->parent != NULL) {
|
199
|
+
oci8_unlink_from_parent(base);
|
200
|
+
}
|
201
|
+
if (parent->children == NULL) {
|
202
|
+
parent->children = base;
|
203
|
+
} else {
|
204
|
+
base->next = parent->children;
|
205
|
+
base->prev = parent->children->prev;
|
206
|
+
parent->children->prev->next = base;
|
207
|
+
parent->children->prev = base;
|
208
|
+
}
|
209
|
+
base->parent = parent;
|
210
|
+
}
|
211
|
+
|
212
|
+
void oci8_unlink_from_parent(oci8_base_t *base)
|
213
|
+
{
|
214
|
+
if (base->parent == NULL) {
|
215
|
+
return;
|
216
|
+
}
|
217
|
+
if (base->next == base) {
|
218
|
+
base->parent->children = NULL;
|
219
|
+
} else {
|
220
|
+
if (base->parent->children == base) {
|
221
|
+
base->parent->children = base->next;
|
222
|
+
}
|
223
|
+
base->next->prev = base->prev;
|
224
|
+
base->prev->next = base->next;
|
225
|
+
base->next = base;
|
226
|
+
base->prev = base;
|
227
|
+
}
|
228
|
+
base->parent = NULL;
|
229
|
+
}
|
230
|
+
|
231
|
+
#ifdef RUBY_VM
|
232
|
+
typedef struct {
|
233
|
+
dvoid *hndlp;
|
234
|
+
OCIError *errhp;
|
235
|
+
} ocibreak_arg_t;
|
236
|
+
|
237
|
+
static VALUE call_OCIBreak(void *user_data)
|
238
|
+
{
|
239
|
+
ocibreak_arg_t *arg = (ocibreak_arg_t *)user_data;
|
240
|
+
OCIBreak(arg->hndlp, arg->errhp);
|
241
|
+
return Qnil;
|
242
|
+
}
|
243
|
+
|
244
|
+
static void oci8_unblock_func(void *user_data)
|
245
|
+
{
|
246
|
+
oci8_svcctx_t *svcctx = (oci8_svcctx_t *)user_data;
|
247
|
+
if (svcctx->base.hp.ptr != NULL) {
|
248
|
+
ocibreak_arg_t arg;
|
249
|
+
arg.hndlp = svcctx->base.hp.ptr;
|
250
|
+
arg.errhp = oci8_errhp;
|
251
|
+
rb_thread_blocking_region(call_OCIBreak, &arg, NULL, NULL);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
/* ruby 1.9 */
|
256
|
+
sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data)
|
257
|
+
{
|
258
|
+
if (svcctx->non_blocking) {
|
259
|
+
sword rv;
|
260
|
+
|
261
|
+
if (!NIL_P(svcctx->executing_thread)) {
|
262
|
+
rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
|
263
|
+
}
|
264
|
+
svcctx->executing_thread = rb_thread_current();
|
265
|
+
rv = (sword)rb_thread_blocking_region(func, data, oci8_unblock_func, svcctx);
|
266
|
+
svcctx->executing_thread = Qnil;
|
267
|
+
if (rv == OCI_ERROR) {
|
268
|
+
if (oci8_get_error_code(oci8_errhp) == 1013) {
|
269
|
+
rb_raise(eOCIBreak, "Canceled by user request.");
|
270
|
+
}
|
271
|
+
}
|
272
|
+
return rv;
|
273
|
+
} else {
|
274
|
+
return (sword)func(data);
|
275
|
+
}
|
276
|
+
}
|
277
|
+
#else /* RUBY_VM */
|
278
|
+
|
279
|
+
/* ruby 1.8 */
|
280
|
+
sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data)
|
281
|
+
{
|
282
|
+
struct timeval tv;
|
283
|
+
sword rv;
|
284
|
+
|
285
|
+
if (!NIL_P(svcctx->executing_thread)) {
|
286
|
+
rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
|
287
|
+
}
|
288
|
+
tv.tv_sec = 0;
|
289
|
+
tv.tv_usec = 100000;
|
290
|
+
svcctx->executing_thread = rb_thread_current();
|
291
|
+
while ((rv = func(data)) == OCI_STILL_EXECUTING) {
|
292
|
+
rb_thread_wait_for(tv);
|
293
|
+
if (tv.tv_usec < 500000)
|
294
|
+
tv.tv_usec <<= 1;
|
295
|
+
}
|
296
|
+
if (rv == OCI_ERROR) {
|
297
|
+
if (oci8_get_error_code(oci8_errhp) == 1013) {
|
298
|
+
if (have_OCIReset)
|
299
|
+
OCIReset(svcctx->base.hp.ptr, oci8_errhp);
|
300
|
+
svcctx->executing_thread = Qnil;
|
301
|
+
rb_raise(eOCIBreak, "Canceled by user request.");
|
302
|
+
}
|
303
|
+
}
|
304
|
+
svcctx->executing_thread = Qnil;
|
305
|
+
return rv;
|
306
|
+
}
|
307
|
+
#endif /* RUBY_VM */
|
308
|
+
|
309
|
+
typedef struct {
|
310
|
+
oci8_svcctx_t *svcctx;
|
311
|
+
const char *sql_text;
|
312
|
+
ub4 num_define_vars;
|
313
|
+
oci8_exec_sql_var_t *define_vars;
|
314
|
+
ub4 num_bind_vars;
|
315
|
+
oci8_exec_sql_var_t *bind_vars;
|
316
|
+
int raise_on_error;
|
317
|
+
OCIStmt *stmtp;
|
318
|
+
} cb_arg_t;
|
319
|
+
|
320
|
+
static VALUE exec_sql(cb_arg_t *arg);
|
321
|
+
static VALUE ensure_func(cb_arg_t *arg);
|
322
|
+
|
323
|
+
/*
|
324
|
+
* utility function to execute a single SQL statement
|
325
|
+
*/
|
326
|
+
sword oci8_exec_sql(oci8_svcctx_t *svcctx, const char *sql_text, ub4 num_define_vars, oci8_exec_sql_var_t *define_vars, ub4 num_bind_vars, oci8_exec_sql_var_t *bind_vars, int raise_on_error)
|
327
|
+
{
|
328
|
+
cb_arg_t arg;
|
329
|
+
|
330
|
+
oci8_check_pid_consistency(svcctx);
|
331
|
+
arg.svcctx = svcctx;
|
332
|
+
arg.sql_text = sql_text;
|
333
|
+
arg.num_define_vars = num_define_vars;
|
334
|
+
arg.define_vars = define_vars;
|
335
|
+
arg.num_bind_vars = num_bind_vars;
|
336
|
+
arg.bind_vars = bind_vars;
|
337
|
+
arg.raise_on_error = raise_on_error;
|
338
|
+
arg.stmtp = NULL;
|
339
|
+
return (sword)rb_ensure(exec_sql, (VALUE)&arg, ensure_func, (VALUE)&arg);
|
340
|
+
}
|
341
|
+
|
342
|
+
static VALUE exec_sql(cb_arg_t *arg)
|
343
|
+
{
|
344
|
+
ub4 pos;
|
345
|
+
sword rv;
|
346
|
+
|
347
|
+
rv = OCIHandleAlloc(oci8_envhp, (dvoid*)&arg->stmtp, OCI_HTYPE_STMT, 0, NULL);
|
348
|
+
if (rv != OCI_SUCCESS) {
|
349
|
+
oci8_env_raise(oci8_envhp, rv);
|
350
|
+
}
|
351
|
+
oci_lc(OCIStmtPrepare(arg->stmtp, oci8_errhp, (text*)arg->sql_text,
|
352
|
+
strlen(arg->sql_text), OCI_NTV_SYNTAX, OCI_DEFAULT));
|
353
|
+
for (pos = 0; pos < arg->num_define_vars; pos++) {
|
354
|
+
arg->define_vars[pos].hp = NULL;
|
355
|
+
oci_lc(OCIDefineByPos(arg->stmtp, (OCIDefine**)&arg->define_vars[pos].hp,
|
356
|
+
oci8_errhp, pos + 1, arg->define_vars[pos].valuep,
|
357
|
+
arg->define_vars[pos].value_sz,
|
358
|
+
arg->define_vars[pos].dty, arg->define_vars[pos].indp,
|
359
|
+
arg->define_vars[pos].alenp, NULL, OCI_DEFAULT));
|
360
|
+
}
|
361
|
+
for (pos = 0; pos < arg->num_bind_vars; pos++) {
|
362
|
+
arg->bind_vars[pos].hp = NULL;
|
363
|
+
oci_lc(OCIBindByPos(arg->stmtp, (OCIBind**)&arg->bind_vars[pos].hp,
|
364
|
+
oci8_errhp, pos + 1, arg->bind_vars[pos].valuep,
|
365
|
+
arg->bind_vars[pos].value_sz, arg->bind_vars[pos].dty,
|
366
|
+
arg->bind_vars[pos].indp, arg->bind_vars[pos].alenp,
|
367
|
+
NULL, 0, NULL, OCI_DEFAULT));
|
368
|
+
}
|
369
|
+
rv = OCIStmtExecute_nb(arg->svcctx, arg->svcctx->base.hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
|
370
|
+
if (rv == OCI_ERROR) {
|
371
|
+
if (oci8_get_error_code(oci8_errhp) == 1000) {
|
372
|
+
/* run GC to close unreferred cursors
|
373
|
+
* when ORA-01000 (maximum open cursors exceeded).
|
374
|
+
*/
|
375
|
+
rb_gc();
|
376
|
+
rv = OCIStmtExecute_nb(arg->svcctx, arg->svcctx->base.hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
|
377
|
+
}
|
378
|
+
}
|
379
|
+
if (arg->raise_on_error) {
|
380
|
+
oci_lc(rv);
|
381
|
+
}
|
382
|
+
return (VALUE)rv;
|
383
|
+
}
|
384
|
+
|
385
|
+
static VALUE ensure_func(cb_arg_t *arg)
|
386
|
+
{
|
387
|
+
if (arg->stmtp != NULL) {
|
388
|
+
OCIHandleFree(arg->stmtp, OCI_HTYPE_STMT);
|
389
|
+
}
|
390
|
+
return Qnil;
|
391
|
+
}
|
392
|
+
|
393
|
+
#if defined RUNTIME_API_CHECK
|
394
|
+
|
395
|
+
#ifndef _WIN32
|
396
|
+
#include <dlfcn.h>
|
397
|
+
#endif
|
398
|
+
|
399
|
+
void *oci8_find_symbol(const char *symbol_name)
|
400
|
+
{
|
401
|
+
#if defined _WIN32
|
402
|
+
/* Windows */
|
403
|
+
static HMODULE hModule = NULL;
|
404
|
+
|
405
|
+
if (hModule == NULL) {
|
406
|
+
hModule = LoadLibrary("OCI.DLL");
|
407
|
+
if (hModule == NULL) {
|
408
|
+
char message[512];
|
409
|
+
int error = GetLastError();
|
410
|
+
char *p;
|
411
|
+
|
412
|
+
memset(message, 0, sizeof(message));
|
413
|
+
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), message, sizeof(message), NULL);
|
414
|
+
for (p = message; *p; p++) {
|
415
|
+
if (*p == '\n' || *p == '\r')
|
416
|
+
*p = ' ';
|
417
|
+
}
|
418
|
+
rb_raise(rb_eLoadError, "OCI.DLL: %d(%s)", error, message);
|
419
|
+
}
|
420
|
+
}
|
421
|
+
return GetProcAddress(hModule, symbol_name);
|
422
|
+
#else
|
423
|
+
/* UNIX */
|
424
|
+
static void *handle = NULL;
|
425
|
+
|
426
|
+
if (handle == NULL) {
|
427
|
+
static const char * const sonames[] = {
|
428
|
+
#if defined(__CYGWIN__)
|
429
|
+
/* Windows(Cygwin) */
|
430
|
+
"OCI.DLL",
|
431
|
+
#elif defined(_AIX)
|
432
|
+
/* AIX */
|
433
|
+
"libclntsh.a(shr.o)",
|
434
|
+
#elif defined(__hppa)
|
435
|
+
/* HP-UX(PA-RISC) */
|
436
|
+
"libclntsh.sl.11.1",
|
437
|
+
"libclntsh.sl.10.1",
|
438
|
+
"libclntsh.sl.9.0",
|
439
|
+
"libclntsh.sl.8.0",
|
440
|
+
#elif defined(__APPLE__)
|
441
|
+
/* Mac OS X */
|
442
|
+
"libclntsh.dylib.11.1",
|
443
|
+
"libclntsh.dylib.10.1",
|
444
|
+
#else
|
445
|
+
/* Linux, Solaris and HP-UX(IA64) */
|
446
|
+
"libclntsh.so.11.1",
|
447
|
+
"libclntsh.so.10.1",
|
448
|
+
"libclntsh.so.9.0",
|
449
|
+
"libclntsh.so.8.0",
|
450
|
+
#endif
|
451
|
+
};
|
452
|
+
#define NUM_SONAMES (sizeof(sonames)/sizeof(sonames[0]))
|
453
|
+
size_t idx;
|
454
|
+
VALUE err = rb_ary_new();
|
455
|
+
|
456
|
+
#ifdef _AIX
|
457
|
+
#define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL|RTLD_MEMBER)
|
458
|
+
#else
|
459
|
+
#define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL)
|
460
|
+
#endif
|
461
|
+
for (idx = 0; idx < NUM_SONAMES; idx++) {
|
462
|
+
handle = dlopen(sonames[idx], DLOPEN_FLAG);
|
463
|
+
if (handle != NULL) {
|
464
|
+
break;
|
465
|
+
}
|
466
|
+
rb_ary_push(err, rb_locale_str_new_cstr(dlerror()));
|
467
|
+
}
|
468
|
+
if (handle == NULL) {
|
469
|
+
VALUE msg;
|
470
|
+
|
471
|
+
msg = rb_str_buf_new(NUM_SONAMES * 50);
|
472
|
+
for (idx = 0; idx < NUM_SONAMES; idx++) {
|
473
|
+
const char *errmsg = RSTRING_PTR(RARRAY_PTR(err)[idx]);
|
474
|
+
if (idx != 0) {
|
475
|
+
rb_str_buf_cat2(msg, " ");
|
476
|
+
}
|
477
|
+
if (strstr(errmsg, sonames[idx]) == NULL) {
|
478
|
+
/* prepend "soname: " if soname is not found in
|
479
|
+
* the error message.
|
480
|
+
*/
|
481
|
+
rb_str_buf_cat2(msg, sonames[idx]);
|
482
|
+
rb_str_buf_cat2(msg, ": ");
|
483
|
+
}
|
484
|
+
rb_str_buf_append(msg, RARRAY_PTR(err)[idx]);
|
485
|
+
rb_str_buf_cat2(msg, ";");
|
486
|
+
}
|
487
|
+
rb_exc_raise(rb_exc_new3(rb_eLoadError, msg));
|
488
|
+
}
|
489
|
+
}
|
490
|
+
return dlsym(handle, symbol_name);
|
491
|
+
#endif /* defined _WIN32 */
|
492
|
+
}
|
493
|
+
#endif /* RUNTIME_API_CHECK */
|