ruby-oci8-master 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }