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.
- data/ChangeLog +2321 -0
- data/Makefile +88 -0
- data/NEWS +303 -0
- data/README +76 -0
- data/VERSION +1 -0
- data/dist-files +83 -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/.document +18 -0
- data/ext/oci8/MANIFEST +18 -0
- data/ext/oci8/apiwrap.c.tmpl +182 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1455 -0
- data/ext/oci8/attr.c +105 -0
- data/ext/oci8/bind.c +366 -0
- data/ext/oci8/connection_pool.c +199 -0
- data/ext/oci8/encoding.c +289 -0
- data/ext/oci8/env.c +178 -0
- data/ext/oci8/error.c +378 -0
- data/ext/oci8/extconf.rb +179 -0
- data/ext/oci8/lob.c +805 -0
- data/ext/oci8/metadata.c +232 -0
- data/ext/oci8/object.c +727 -0
- data/ext/oci8/oci8.c +1156 -0
- data/ext/oci8/oci8.h +574 -0
- data/ext/oci8/oci8lib.c +527 -0
- data/ext/oci8/ocidatetime.c +484 -0
- data/ext/oci8/ocihandle.c +751 -0
- data/ext/oci8/ocinumber.c +1612 -0
- data/ext/oci8/oraconf.rb +1119 -0
- data/ext/oci8/oradate.c +611 -0
- data/ext/oci8/oranumber_util.c +352 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/stmt.c +673 -0
- data/ext/oci8/thread_util.c +85 -0
- data/ext/oci8/thread_util.h +30 -0
- data/ext/oci8/win32.c +137 -0
- data/lib/.document +1 -0
- data/lib/dbd/OCI8.rb +591 -0
- data/lib/oci8.rb.in +94 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +349 -0
- data/lib/oci8/compat.rb +113 -0
- data/lib/oci8/connection_pool.rb +99 -0
- data/lib/oci8/datetime.rb +611 -0
- data/lib/oci8/encoding-init.rb +74 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2132 -0
- data/lib/oci8/object.rb +581 -0
- data/lib/oci8/oci8.rb +721 -0
- data/lib/oci8/ocihandle.rb +425 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/lib/oci8/properties.rb +73 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +63 -0
- data/setup.rb +1331 -0
- data/test/README +4 -0
- data/test/config.rb +122 -0
- data/test/test_all.rb +51 -0
- data/test/test_appinfo.rb +63 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +46 -0
- data/test/test_bind_time.rb +178 -0
- data/test/test_break.rb +96 -0
- data/test/test_clob.rb +82 -0
- data/test/test_connstr.rb +81 -0
- data/test/test_datetime.rb +582 -0
- data/test/test_dbi.rb +366 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +100 -0
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1399 -0
- data/test/test_oci8.rb +434 -0
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +256 -0
- data/test/test_oranumber.rb +746 -0
- data/test/test_rowid.rb +33 -0
- metadata +137 -0
data/ext/oci8/oci8lib.c
ADDED
@@ -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
|
+
}
|