ruby-oci8-master 2.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/ChangeLog +2321 -0
  2. data/Makefile +88 -0
  3. data/NEWS +303 -0
  4. data/README +76 -0
  5. data/VERSION +1 -0
  6. data/dist-files +83 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/.document +18 -0
  13. data/ext/oci8/MANIFEST +18 -0
  14. data/ext/oci8/apiwrap.c.tmpl +182 -0
  15. data/ext/oci8/apiwrap.h.tmpl +61 -0
  16. data/ext/oci8/apiwrap.rb +91 -0
  17. data/ext/oci8/apiwrap.yml +1455 -0
  18. data/ext/oci8/attr.c +105 -0
  19. data/ext/oci8/bind.c +366 -0
  20. data/ext/oci8/connection_pool.c +199 -0
  21. data/ext/oci8/encoding.c +289 -0
  22. data/ext/oci8/env.c +178 -0
  23. data/ext/oci8/error.c +378 -0
  24. data/ext/oci8/extconf.rb +179 -0
  25. data/ext/oci8/lob.c +805 -0
  26. data/ext/oci8/metadata.c +232 -0
  27. data/ext/oci8/object.c +727 -0
  28. data/ext/oci8/oci8.c +1156 -0
  29. data/ext/oci8/oci8.h +574 -0
  30. data/ext/oci8/oci8lib.c +527 -0
  31. data/ext/oci8/ocidatetime.c +484 -0
  32. data/ext/oci8/ocihandle.c +751 -0
  33. data/ext/oci8/ocinumber.c +1612 -0
  34. data/ext/oci8/oraconf.rb +1119 -0
  35. data/ext/oci8/oradate.c +611 -0
  36. data/ext/oci8/oranumber_util.c +352 -0
  37. data/ext/oci8/oranumber_util.h +24 -0
  38. data/ext/oci8/post-config.rb +5 -0
  39. data/ext/oci8/stmt.c +673 -0
  40. data/ext/oci8/thread_util.c +85 -0
  41. data/ext/oci8/thread_util.h +30 -0
  42. data/ext/oci8/win32.c +137 -0
  43. data/lib/.document +1 -0
  44. data/lib/dbd/OCI8.rb +591 -0
  45. data/lib/oci8.rb.in +94 -0
  46. data/lib/oci8/.document +8 -0
  47. data/lib/oci8/bindtype.rb +349 -0
  48. data/lib/oci8/compat.rb +113 -0
  49. data/lib/oci8/connection_pool.rb +99 -0
  50. data/lib/oci8/datetime.rb +611 -0
  51. data/lib/oci8/encoding-init.rb +74 -0
  52. data/lib/oci8/encoding.yml +537 -0
  53. data/lib/oci8/metadata.rb +2132 -0
  54. data/lib/oci8/object.rb +581 -0
  55. data/lib/oci8/oci8.rb +721 -0
  56. data/lib/oci8/ocihandle.rb +425 -0
  57. data/lib/oci8/oracle_version.rb +144 -0
  58. data/lib/oci8/properties.rb +73 -0
  59. data/metaconfig +142 -0
  60. data/pre-distclean.rb +7 -0
  61. data/ruby-oci8.gemspec +63 -0
  62. data/setup.rb +1331 -0
  63. data/test/README +4 -0
  64. data/test/config.rb +122 -0
  65. data/test/test_all.rb +51 -0
  66. data/test/test_appinfo.rb +63 -0
  67. data/test/test_array_dml.rb +333 -0
  68. data/test/test_bind_raw.rb +46 -0
  69. data/test/test_bind_time.rb +178 -0
  70. data/test/test_break.rb +96 -0
  71. data/test/test_clob.rb +82 -0
  72. data/test/test_connstr.rb +81 -0
  73. data/test/test_datetime.rb +582 -0
  74. data/test/test_dbi.rb +366 -0
  75. data/test/test_dbi_clob.rb +53 -0
  76. data/test/test_encoding.rb +100 -0
  77. data/test/test_error.rb +88 -0
  78. data/test/test_metadata.rb +1399 -0
  79. data/test/test_oci8.rb +434 -0
  80. data/test/test_oracle_version.rb +70 -0
  81. data/test/test_oradate.rb +256 -0
  82. data/test/test_oranumber.rb +746 -0
  83. data/test/test_rowid.rb +33 -0
  84. metadata +137 -0
@@ -0,0 +1,527 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright (C) 2002-2011 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
+ ID oci8_id_at_last_error;
14
+ ID oci8_id_new;
15
+ ID oci8_id_get;
16
+ ID oci8_id_set;
17
+ ID oci8_id_keys;
18
+ ID oci8_id_oci8_vtable;
19
+ #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID
20
+ ID oci8_id_add_op;
21
+ ID oci8_id_sub_op;
22
+ ID oci8_id_mul_op;
23
+ ID oci8_id_div_op;
24
+ #endif
25
+ int oci8_in_finalizer = 0;
26
+ VALUE oci8_cOCIHandle;
27
+
28
+
29
+ static VALUE mOCI8BindType;
30
+ static VALUE cOCI8BindTypeBase;
31
+
32
+ void oci8_base_free(oci8_base_t *base)
33
+ {
34
+ while (base->children != NULL) {
35
+ oci8_base_free(base->children);
36
+ }
37
+ oci8_unlink_from_parent(base);
38
+ if (base->vptr->free != NULL)
39
+ base->vptr->free(base);
40
+ if (base->type >= OCI_DTYPE_FIRST)
41
+ OCIDescriptorFree(base->hp.ptr, base->type);
42
+ else if (base->type >= OCI_HTYPE_FIRST)
43
+ OCIHandleFree(base->hp.ptr, base->type);
44
+ base->type = 0;
45
+ base->hp.ptr = NULL;
46
+ }
47
+
48
+ #ifdef HAVE_RB_SET_END_PROC
49
+ static void at_exit_func(VALUE val)
50
+ {
51
+ oci8_in_finalizer = 1;
52
+ }
53
+ #endif
54
+
55
+ #ifdef _WIN32
56
+ __declspec(dllexport)
57
+ #endif
58
+ void
59
+ Init_oci8lib()
60
+ {
61
+ VALUE cOCI8;
62
+ OCIEnv *envhp;
63
+ OCIError *errhp;
64
+ sword rv;
65
+
66
+ #ifdef RUNTIME_API_CHECK
67
+ Init_oci8_apiwrap();
68
+ if (oracle_client_version < ORAVER_9_0) {
69
+ rb_raise(rb_eLoadError, "Oracle 8 (8.0) and Oracle 8i (8.1) is not supported anymore!");
70
+ }
71
+
72
+ if (have_OCIClientVersion) {
73
+ sword major, minor, update, patch, port_update;
74
+ OCIClientVersion(&major, &minor, &update, &patch, &port_update);
75
+ oracle_client_version = ORAVERNUM(major, minor, update, patch, port_update);
76
+ }
77
+ #endif
78
+
79
+ oci8_id_at_last_error = rb_intern("@last_error");
80
+ oci8_id_new = rb_intern("new");
81
+ oci8_id_get = rb_intern("get");
82
+ oci8_id_set = rb_intern("set");
83
+ oci8_id_keys = rb_intern("keys");
84
+ oci8_id_oci8_vtable = rb_intern("__oci8_vtable__");
85
+ #ifdef CHAR_IS_NOT_A_SHORTCUT_TO_ID
86
+ oci8_id_add_op = rb_intern("+");
87
+ oci8_id_sub_op = rb_intern("-");
88
+ oci8_id_mul_op = rb_intern("*");
89
+ oci8_id_div_op = rb_intern("/");
90
+ #endif
91
+ #ifdef HAVE_RB_SET_END_PROC
92
+ rb_set_end_proc(at_exit_func, Qnil);
93
+ #endif
94
+
95
+ Init_oci8_thread_util();
96
+ Init_oci8_error();
97
+ Init_oci8_env();
98
+
99
+ /* OCIHandle class */
100
+ Init_oci8_handle();
101
+
102
+ /* OCI8 class */
103
+ cOCI8 = Init_oci8();
104
+
105
+ /* OCI8::ConnectionPool class */
106
+ Init_oci8_connection_pool(cOCI8);
107
+
108
+ /* OCI8::BindType module */
109
+ mOCI8BindType = rb_define_module_under(cOCI8, "BindType");
110
+ /* OCI8::BindType::Base class */
111
+ cOCI8BindTypeBase = rb_define_class_under(mOCI8BindType, "Base", oci8_cOCIHandle);
112
+
113
+ /* Handle */
114
+ Init_oci8_bind(cOCI8BindTypeBase);
115
+ Init_oci8_stmt(cOCI8);
116
+
117
+ /* Encoding */
118
+ Init_oci8_encoding(cOCI8);
119
+
120
+ /* register allocators */
121
+ Init_oci8_metadata(cOCI8);
122
+ Init_oci8_lob(cOCI8);
123
+
124
+ /* allocate a temporary errhp to pass Init_oci_number() */
125
+ rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
126
+ if (rv != OCI_SUCCESS) {
127
+ oci8_raise_init_error();
128
+ }
129
+ rv = OCIHandleAlloc(envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
130
+ if (rv != OCI_SUCCESS)
131
+ oci8_env_raise(envhp, rv);
132
+ Init_oci_number(cOCI8, errhp);
133
+ OCIHandleFree(errhp, OCI_HTYPE_ERROR);
134
+ OCIHandleFree(envhp, OCI_HTYPE_ENV);
135
+
136
+ Init_ora_date();
137
+ Init_oci_datetime();
138
+ Init_oci_object(cOCI8);
139
+
140
+ #ifdef USE_WIN32_C
141
+ Init_oci8_win32(cOCI8);
142
+ #endif
143
+
144
+ #ifdef DEBUG_CORE_FILE
145
+ signal(SIGSEGV, SIG_DFL);
146
+ #endif
147
+ }
148
+
149
+ VALUE oci8_define_class(const char *name, oci8_base_vtable_t *vptr)
150
+ {
151
+ VALUE klass = rb_define_class(name, oci8_cOCIHandle);
152
+ VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr);
153
+ rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
154
+ return klass;
155
+ }
156
+
157
+ VALUE oci8_define_class_under(VALUE outer, const char *name, oci8_base_vtable_t *vptr)
158
+ {
159
+ VALUE klass = rb_define_class_under(outer, name, oci8_cOCIHandle);
160
+ VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, vptr);
161
+ rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
162
+ return klass;
163
+ }
164
+
165
+ VALUE oci8_define_bind_class(const char *name, const oci8_bind_vtable_t *vptr)
166
+ {
167
+ VALUE klass = rb_define_class_under(mOCI8BindType, name, cOCI8BindTypeBase);
168
+ VALUE obj = Data_Wrap_Struct(rb_cObject, 0, 0, (void*)vptr);
169
+ rb_ivar_set(klass, oci8_id_oci8_vtable, obj);
170
+ return klass;
171
+ }
172
+
173
+ void oci8_link_to_parent(oci8_base_t *base, oci8_base_t *parent)
174
+ {
175
+ if (base->parent != NULL) {
176
+ oci8_unlink_from_parent(base);
177
+ }
178
+ if (parent->children == NULL) {
179
+ parent->children = base;
180
+ } else {
181
+ base->next = parent->children;
182
+ base->prev = parent->children->prev;
183
+ parent->children->prev->next = base;
184
+ parent->children->prev = base;
185
+ }
186
+ base->parent = parent;
187
+ }
188
+
189
+ void oci8_unlink_from_parent(oci8_base_t *base)
190
+ {
191
+ if (base->parent == NULL) {
192
+ return;
193
+ }
194
+ if (base->next == base) {
195
+ base->parent->children = NULL;
196
+ } else {
197
+ if (base->parent->children == base) {
198
+ base->parent->children = base->next;
199
+ }
200
+ base->next->prev = base->prev;
201
+ base->prev->next = base->next;
202
+ base->next = base;
203
+ base->prev = base;
204
+ }
205
+ base->parent = NULL;
206
+ }
207
+
208
+ #ifdef HAVE_RB_THREAD_BLOCKING_REGION
209
+
210
+ #if 0
211
+ typedef struct {
212
+ dvoid *hndlp;
213
+ OCIError *errhp;
214
+ } ocibreak_arg_t;
215
+
216
+ static VALUE call_OCIBreak(void *user_data)
217
+ {
218
+ ocibreak_arg_t *arg = (ocibreak_arg_t *)user_data;
219
+ OCIBreak(arg->hndlp, arg->errhp);
220
+ return Qnil;
221
+ }
222
+
223
+ static void oci8_unblock_func(void *user_data)
224
+ {
225
+ oci8_svcctx_t *svcctx = (oci8_svcctx_t *)user_data;
226
+ if (svcctx->base.hp.ptr != NULL) {
227
+ ocibreak_arg_t arg;
228
+ arg.hndlp = svcctx->base.hp.ptr;
229
+ arg.errhp = oci8_errhp;
230
+ rb_thread_blocking_region(call_OCIBreak, &arg, NULL, NULL);
231
+ }
232
+ }
233
+ #else
234
+ static void oci8_unblock_func(void *user_data)
235
+ {
236
+ oci8_svcctx_t *svcctx = (oci8_svcctx_t *)user_data;
237
+ OCIBreak(svcctx->base.hp.ptr, oci8_errhp);
238
+ }
239
+ #endif
240
+
241
+ /* ruby 1.9 */
242
+ sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data)
243
+ {
244
+ if (svcctx->non_blocking) {
245
+ sword rv;
246
+
247
+ if (!NIL_P(svcctx->executing_thread)) {
248
+ rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
249
+ }
250
+ svcctx->executing_thread = rb_thread_current();
251
+ /* Note: executing_thread is cleard at the end of the blocking function. */
252
+ rv = (sword)rb_thread_blocking_region(func, data, oci8_unblock_func, svcctx);
253
+ if (rv == OCI_ERROR) {
254
+ if (oci8_get_error_code(oci8_errhp) == 1013) {
255
+ rb_raise(eOCIBreak, "Canceled by user request.");
256
+ }
257
+ }
258
+ return rv;
259
+ } else {
260
+ return (sword)func(data);
261
+ }
262
+ }
263
+ #else /* HAVE_RB_THREAD_BLOCKING_REGION */
264
+
265
+ /* ruby 1.8 */
266
+ typedef struct {
267
+ oci8_svcctx_t *svcctx;
268
+ rb_blocking_function_t *func;
269
+ void *data;
270
+ } blocking_region_arg_t;
271
+
272
+ static VALUE blocking_function_execute(blocking_region_arg_t *arg)
273
+ {
274
+ oci8_svcctx_t *svcctx = arg->svcctx;
275
+ rb_blocking_function_t *func = arg->func;
276
+ void *data = arg->data;
277
+ struct timeval tv;
278
+ sword rv;
279
+
280
+ tv.tv_sec = 0;
281
+ tv.tv_usec = 10000;
282
+ svcctx->executing_thread = rb_thread_current();
283
+ while ((rv = func(data)) == OCI_STILL_EXECUTING) {
284
+ rb_thread_wait_for(tv);
285
+ if (tv.tv_usec < 500000)
286
+ tv.tv_usec <<= 1;
287
+ }
288
+ if (rv == OCI_ERROR) {
289
+ if (oci8_get_error_code(oci8_errhp) == 1013) {
290
+ OCIReset(svcctx->base.hp.ptr, oci8_errhp);
291
+ svcctx->executing_thread = Qnil;
292
+ rb_raise(eOCIBreak, "Canceled by user request.");
293
+ }
294
+ }
295
+ svcctx->executing_thread = Qnil;
296
+ return rv;
297
+ }
298
+
299
+ static VALUE blocking_function_ensure(oci8_svcctx_t *svcctx)
300
+ {
301
+ if (!NIL_P(svcctx->executing_thread)) {
302
+ /* The thread is killed. */
303
+ OCIBreak(svcctx->base.hp.ptr, oci8_errhp);
304
+ OCIReset(svcctx->base.hp.ptr, oci8_errhp);
305
+ svcctx->executing_thread = Qnil;
306
+ }
307
+ return Qnil;
308
+ }
309
+
310
+ sword oci8_blocking_region(oci8_svcctx_t *svcctx, rb_blocking_function_t func, void *data)
311
+ {
312
+ blocking_region_arg_t arg;
313
+
314
+ arg.svcctx = svcctx;
315
+ arg.func = func;
316
+ arg.data = data;
317
+ if (!NIL_P(svcctx->executing_thread)) {
318
+ rb_raise(rb_eRuntimeError, "executing in another thread");
319
+ }
320
+ return (sword)rb_ensure(blocking_function_execute, (VALUE)&arg, blocking_function_ensure, (VALUE)svcctx);
321
+ }
322
+ #endif /* HAVE_RB_THREAD_BLOCKING_REGION */
323
+
324
+ typedef struct {
325
+ oci8_svcctx_t *svcctx;
326
+ const char *sql_text;
327
+ ub4 num_define_vars;
328
+ oci8_exec_sql_var_t *define_vars;
329
+ ub4 num_bind_vars;
330
+ oci8_exec_sql_var_t *bind_vars;
331
+ int raise_on_error;
332
+ OCIStmt *stmtp;
333
+ } cb_arg_t;
334
+
335
+ static VALUE exec_sql(cb_arg_t *arg);
336
+ static VALUE ensure_func(cb_arg_t *arg);
337
+
338
+ /*
339
+ * utility function to execute a single SQL statement
340
+ */
341
+ 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)
342
+ {
343
+ cb_arg_t arg;
344
+
345
+ oci8_check_pid_consistency(svcctx);
346
+ arg.svcctx = svcctx;
347
+ arg.sql_text = sql_text;
348
+ arg.num_define_vars = num_define_vars;
349
+ arg.define_vars = define_vars;
350
+ arg.num_bind_vars = num_bind_vars;
351
+ arg.bind_vars = bind_vars;
352
+ arg.raise_on_error = raise_on_error;
353
+ arg.stmtp = NULL;
354
+ return (sword)rb_ensure(exec_sql, (VALUE)&arg, ensure_func, (VALUE)&arg);
355
+ }
356
+
357
+ static VALUE exec_sql(cb_arg_t *arg)
358
+ {
359
+ ub4 pos;
360
+ sword rv;
361
+
362
+ rv = OCIHandleAlloc(oci8_envhp, (dvoid*)&arg->stmtp, OCI_HTYPE_STMT, 0, NULL);
363
+ if (rv != OCI_SUCCESS) {
364
+ oci8_env_raise(oci8_envhp, rv);
365
+ }
366
+ chker2(OCIStmtPrepare(arg->stmtp, oci8_errhp, (text*)arg->sql_text,
367
+ strlen(arg->sql_text), OCI_NTV_SYNTAX, OCI_DEFAULT),
368
+ &arg->svcctx->base);
369
+ for (pos = 0; pos < arg->num_define_vars; pos++) {
370
+ arg->define_vars[pos].hp = NULL;
371
+ chker3(OCIDefineByPos(arg->stmtp, (OCIDefine**)&arg->define_vars[pos].hp,
372
+ oci8_errhp, pos + 1, arg->define_vars[pos].valuep,
373
+ arg->define_vars[pos].value_sz,
374
+ arg->define_vars[pos].dty, arg->define_vars[pos].indp,
375
+ arg->define_vars[pos].alenp, NULL, OCI_DEFAULT),
376
+ &arg->svcctx->base, arg->stmtp);
377
+ }
378
+ for (pos = 0; pos < arg->num_bind_vars; pos++) {
379
+ arg->bind_vars[pos].hp = NULL;
380
+ chker3(OCIBindByPos(arg->stmtp, (OCIBind**)&arg->bind_vars[pos].hp,
381
+ oci8_errhp, pos + 1, arg->bind_vars[pos].valuep,
382
+ arg->bind_vars[pos].value_sz, arg->bind_vars[pos].dty,
383
+ arg->bind_vars[pos].indp, arg->bind_vars[pos].alenp,
384
+ NULL, 0, NULL, OCI_DEFAULT),
385
+ &arg->svcctx->base, arg->stmtp);
386
+ }
387
+ rv = OCIStmtExecute_nb(arg->svcctx, arg->svcctx->base.hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
388
+ if (rv == OCI_ERROR) {
389
+ if (oci8_get_error_code(oci8_errhp) == 1000) {
390
+ /* run GC to close unreferred cursors
391
+ * when ORA-01000 (maximum open cursors exceeded).
392
+ */
393
+ rb_gc();
394
+ rv = OCIStmtExecute_nb(arg->svcctx, arg->svcctx->base.hp.svc, arg->stmtp, oci8_errhp, 1, 0, NULL, NULL, OCI_DEFAULT);
395
+ }
396
+ }
397
+ if (arg->raise_on_error) {
398
+ chker3(rv, &arg->svcctx->base, arg->stmtp);
399
+ }
400
+ return (VALUE)rv;
401
+ }
402
+
403
+ static VALUE ensure_func(cb_arg_t *arg)
404
+ {
405
+ if (arg->stmtp != NULL) {
406
+ OCIHandleFree(arg->stmtp, OCI_HTYPE_STMT);
407
+ }
408
+ return Qnil;
409
+ }
410
+
411
+ #if defined RUNTIME_API_CHECK
412
+
413
+ #ifndef _WIN32
414
+ #include <dlfcn.h>
415
+ #endif
416
+
417
+ void *oci8_find_symbol(const char *symbol_name)
418
+ {
419
+ #if defined _WIN32
420
+ /* Windows */
421
+ static HMODULE hModule = NULL;
422
+
423
+ if (hModule == NULL) {
424
+ hModule = LoadLibrary("OCI.DLL");
425
+ if (hModule == NULL) {
426
+ char message[512];
427
+ int error = GetLastError();
428
+ char *p;
429
+
430
+ memset(message, 0, sizeof(message));
431
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), message, sizeof(message), NULL);
432
+ for (p = message; *p; p++) {
433
+ if (*p == '\n' || *p == '\r')
434
+ *p = ' ';
435
+ }
436
+ rb_raise(rb_eLoadError, "OCI.DLL: %d(%s)", error, message);
437
+ }
438
+ }
439
+ return GetProcAddress(hModule, symbol_name);
440
+ #else
441
+ /* UNIX */
442
+ static void *handle = NULL;
443
+
444
+ if (handle == NULL) {
445
+ static const char * const sonames[] = {
446
+ #if defined(__CYGWIN__)
447
+ /* Windows(Cygwin) */
448
+ "OCI.DLL",
449
+ #elif defined(_AIX)
450
+ /* AIX */
451
+ "libclntsh.a(shr.o)",
452
+ #elif defined(__hppa)
453
+ /* HP-UX(PA-RISC) */
454
+ "libclntsh.sl.11.1",
455
+ "libclntsh.sl.10.1",
456
+ "libclntsh.sl.9.0",
457
+ "libclntsh.sl.8.0",
458
+ #elif defined(__APPLE__)
459
+ /* Mac OS X */
460
+ "libclntsh.dylib.11.1",
461
+ "libclntsh.dylib.10.1",
462
+ #else
463
+ /* Linux, Solaris and HP-UX(IA64) */
464
+ "libclntsh.so.11.1",
465
+ "libclntsh.so.10.1",
466
+ "libclntsh.so.9.0",
467
+ "libclntsh.so.8.0",
468
+ #endif
469
+ };
470
+ #define NUM_SONAMES (sizeof(sonames)/sizeof(sonames[0]))
471
+ size_t idx;
472
+ VALUE err = rb_ary_new();
473
+
474
+ #ifdef _AIX
475
+ #define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL|RTLD_MEMBER)
476
+ #else
477
+ #define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL)
478
+ #endif
479
+ for (idx = 0; idx < NUM_SONAMES; idx++) {
480
+ handle = dlopen(sonames[idx], DLOPEN_FLAG);
481
+ if (handle != NULL) {
482
+ break;
483
+ }
484
+ rb_ary_push(err, rb_locale_str_new_cstr(dlerror()));
485
+ }
486
+ if (handle == NULL) {
487
+ VALUE msg;
488
+
489
+ msg = rb_str_buf_new(NUM_SONAMES * 50);
490
+ for (idx = 0; idx < NUM_SONAMES; idx++) {
491
+ const char *errmsg = RSTRING_PTR(RARRAY_PTR(err)[idx]);
492
+ if (idx != 0) {
493
+ rb_str_buf_cat2(msg, " ");
494
+ }
495
+ if (strstr(errmsg, sonames[idx]) == NULL) {
496
+ /* prepend "soname: " if soname is not found in
497
+ * the error message.
498
+ */
499
+ rb_str_buf_cat2(msg, sonames[idx]);
500
+ rb_str_buf_cat2(msg, ": ");
501
+ }
502
+ rb_str_buf_append(msg, RARRAY_PTR(err)[idx]);
503
+ rb_str_buf_cat2(msg, ";");
504
+ }
505
+ rb_exc_raise(rb_exc_new3(rb_eLoadError, msg));
506
+ }
507
+ }
508
+ return dlsym(handle, symbol_name);
509
+ #endif /* defined _WIN32 */
510
+ }
511
+ #endif /* RUNTIME_API_CHECK */
512
+
513
+ oci8_base_t *oci8_get_handle(VALUE obj, VALUE klass)
514
+ {
515
+ oci8_base_t *hp;
516
+
517
+ if (!rb_obj_is_kind_of(obj, klass)) {
518
+ rb_raise(rb_eTypeError, "invalid argument %s (expect %s)",
519
+ rb_obj_classname(obj), rb_class2name(klass));
520
+ }
521
+ Data_Get_Struct(obj, oci8_base_t, hp);
522
+ if (hp->type == 0) {
523
+ rb_raise(eOCIException, "%s was already closed.",
524
+ rb_obj_classname(obj));
525
+ }
526
+ return hp;
527
+ }