ruby-oci8 2.2.3 → 2.2.12
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.
- checksums.yaml +7 -0
- data/ChangeLog +427 -0
- data/NEWS +335 -42
- data/README.md +20 -9
- data/dist-files +9 -3
- data/docs/bind-array-to-in_cond.md +2 -2
- data/docs/conflicts-local-connections-and-processes.md +7 -4
- data/docs/hanging-after-inactivity.md +63 -0
- data/docs/install-binary-package.md +15 -11
- data/docs/install-full-client.md +18 -21
- data/docs/install-instant-client.md +45 -27
- data/docs/install-on-osx.md +31 -120
- data/docs/ldap-auth-and-function-interposition.md +123 -0
- data/docs/number-type-mapping.md +79 -0
- data/docs/platform-specific-issues.md +17 -50
- data/docs/report-installation-issue.md +3 -0
- data/docs/timeout-parameters.md +3 -0
- data/ext/oci8/apiwrap.c.tmpl +2 -5
- data/ext/oci8/apiwrap.rb +6 -1
- data/ext/oci8/apiwrap.yml +34 -22
- data/ext/oci8/attr.c +4 -2
- data/ext/oci8/bind.c +366 -6
- data/ext/oci8/connection_pool.c +3 -3
- data/ext/oci8/encoding.c +5 -5
- data/ext/oci8/env.c +8 -2
- data/ext/oci8/error.c +24 -16
- data/ext/oci8/extconf.rb +8 -4
- data/ext/oci8/hook_funcs.c +274 -61
- data/ext/oci8/lob.c +31 -75
- data/ext/oci8/metadata.c +2 -2
- data/ext/oci8/object.c +72 -27
- data/ext/oci8/oci8.c +45 -132
- data/ext/oci8/oci8.h +32 -88
- data/ext/oci8/oci8lib.c +178 -38
- data/ext/oci8/ocihandle.c +37 -37
- data/ext/oci8/ocinumber.c +23 -18
- data/ext/oci8/oraconf.rb +158 -339
- data/ext/oci8/oradate.c +19 -19
- data/ext/oci8/plthook.h +10 -0
- data/ext/oci8/plthook_elf.c +433 -268
- data/ext/oci8/plthook_osx.c +40 -9
- data/ext/oci8/plthook_win32.c +9 -0
- data/ext/oci8/stmt.c +52 -17
- data/ext/oci8/win32.c +4 -22
- data/lib/oci8/bindtype.rb +1 -15
- data/lib/oci8/check_load_error.rb +57 -10
- data/lib/oci8/cursor.rb +57 -25
- data/lib/oci8/metadata.rb +9 -1
- data/lib/oci8/object.rb +10 -0
- data/lib/oci8/oci8.rb +33 -28
- data/lib/oci8/oracle_version.rb +11 -1
- data/lib/oci8/properties.rb +22 -0
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +48 -4
- data/lib/ruby-oci8.rb +0 -3
- data/pre-distclean.rb +1 -3
- data/ruby-oci8.gemspec +3 -8
- data/setup.rb +11 -2
- data/test/README.md +37 -0
- data/test/config.rb +1 -1
- data/test/setup_test_object.sql +21 -13
- data/test/setup_test_package.sql +59 -0
- data/test/test_all.rb +2 -0
- data/test/test_bind_boolean.rb +99 -0
- data/test/test_bind_integer.rb +47 -0
- data/test/test_break.rb +11 -9
- data/test/test_clob.rb +4 -16
- data/test/test_connstr.rb +29 -13
- data/test/test_datetime.rb +8 -3
- data/test/test_object.rb +27 -9
- data/test/test_oci8.rb +170 -46
- data/test/test_oranumber.rb +12 -6
- data/test/test_package_type.rb +15 -3
- data/test/test_properties.rb +17 -0
- metadata +40 -54
- data/docs/osx-install-dev-tools.png +0 -0
- data/test/README +0 -42
data/ext/oci8/oci8.h
CHANGED
@@ -21,8 +21,23 @@ extern "C"
|
|
21
21
|
}
|
22
22
|
#endif
|
23
23
|
|
24
|
+
/*
|
25
|
+
* Oracle version number format in 32-bit integer.
|
26
|
+
*
|
27
|
+
* Oracle 12c or earier Oracle 18c or later
|
28
|
+
*
|
29
|
+
* hexadecimal -> dotted version number hexadecimal -> dotted version number
|
30
|
+
* 0c102304 -> 12.1.2.3.4 12012034 -> 18.1.2.3.4
|
31
|
+
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
32
|
+
* 0c ------------' | | | | 2 bytes 12 ------------' | | | | 2 bytes
|
33
|
+
* 1 --------------' | | | 1 byte 01 -------------' | | | 2 bytes
|
34
|
+
* 02 --------------' | | 2 bytes 2 --------------' | | 1 byte
|
35
|
+
* 3 ---------------' | 1 byte 03 --------------' | 2 bytes
|
36
|
+
* 04 ---------------' 2 bytes 4 ---------------' 1 byte
|
37
|
+
*/
|
24
38
|
#define ORAVERNUM(major, minor, update, patch, port_update) \
|
25
|
-
(((major) << 24) | ((minor) <<
|
39
|
+
(((major) >= 18) ? (((major) << 24) | ((minor) << 16) | ((update) << 12) | ((patch) << 4) | (port_update)) \
|
40
|
+
: (((major) << 24) | ((minor) << 20) | ((update) << 12) | ((patch) << 8) | (port_update)))
|
26
41
|
|
27
42
|
#define ORAVER_8_0 ORAVERNUM(8, 0, 0, 0, 0)
|
28
43
|
#define ORAVER_8_1 ORAVERNUM(8, 1, 0, 0, 0)
|
@@ -32,6 +47,7 @@ extern "C"
|
|
32
47
|
#define ORAVER_10_2 ORAVERNUM(10, 2, 0, 0, 0)
|
33
48
|
#define ORAVER_11_1 ORAVERNUM(11, 1, 0, 0, 0)
|
34
49
|
#define ORAVER_12_1 ORAVERNUM(12, 1, 0, 0, 0)
|
50
|
+
#define ORAVER_18 ORAVERNUM(18, 0, 0, 0, 0)
|
35
51
|
|
36
52
|
#include "extconf.h"
|
37
53
|
#include <ruby/encoding.h>
|
@@ -73,88 +89,6 @@ typedef orasb8 sb8;
|
|
73
89
|
#endif
|
74
90
|
#endif
|
75
91
|
|
76
|
-
/*
|
77
|
-
* Use TypedData on ruby 1.9.3 and later.
|
78
|
-
*/
|
79
|
-
#ifndef HAVE_RB_DATA_TYPE_T_FUNCTION
|
80
|
-
|
81
|
-
/*
|
82
|
-
* Don't use TypedData even though ruby 1.9.2 has it because the
|
83
|
-
* definitions are slightly different from ruby 1.9.3 and later.
|
84
|
-
*/
|
85
|
-
#define rb_data_type_t oci8_data_type_t
|
86
|
-
#undef TypedData_Make_Struct
|
87
|
-
#undef TypedData_Wrap_Struct
|
88
|
-
#undef TypedData_Get_Struct
|
89
|
-
#undef RTYPEDDATA_DATA
|
90
|
-
#undef RUBY_DEFAULT_FREE
|
91
|
-
|
92
|
-
/*
|
93
|
-
* To pass compilation on ruby 1.9.2 and earlier.
|
94
|
-
*/
|
95
|
-
typedef struct oci8_data_type_struct rb_data_type_t;
|
96
|
-
struct oci8_data_type_struct {
|
97
|
-
const char *wrap_struct_name;
|
98
|
-
struct {
|
99
|
-
void (*dmark)(void*);
|
100
|
-
void (*dfree)(void*);
|
101
|
-
size_t (*dsize)(const void *);
|
102
|
-
} function;
|
103
|
-
const rb_data_type_t *parent;
|
104
|
-
void *data;
|
105
|
-
};
|
106
|
-
#define TypedData_Make_Struct(klass, type, data_type, sval) \
|
107
|
-
Data_Make_Struct((klass), type, (data_type)->function.dmark, (data_type)->function.dfree, (sval))
|
108
|
-
#define TypedData_Wrap_Struct(klass, data_type, sval) \
|
109
|
-
Data_Wrap_Struct((klass), (data_type)->function.dmark, (data_type)->function.dfree, (sval))
|
110
|
-
#define TypedData_Get_Struct(obj, type, data_type, sval) \
|
111
|
-
Data_Get_Struct((obj), type, (sval))
|
112
|
-
#define RTYPEDDATA_DATA(obj) DATA_PTR(obj)
|
113
|
-
#define RUBY_DEFAULT_FREE xfree
|
114
|
-
#endif
|
115
|
-
|
116
|
-
/* a new function in ruby 1.9.3.
|
117
|
-
* define a compatible macro for ruby 1.9.2 or lower.
|
118
|
-
*/
|
119
|
-
#ifndef HAVE_RB_CLASS_SUPERCLASS
|
120
|
-
#ifdef RCLASS_SUPER
|
121
|
-
#define rb_class_superclass(cls) RCLASS_SUPER(cls)
|
122
|
-
#else
|
123
|
-
#define rb_class_superclass(cls) (RCLASS(cls)->super)
|
124
|
-
#endif
|
125
|
-
#endif
|
126
|
-
|
127
|
-
/* new macros in ruby 2.1.0
|
128
|
-
*/
|
129
|
-
#ifndef RARRAY_AREF
|
130
|
-
#define RARRAY_AREF(a, i) (RARRAY_PTR(a)[i])
|
131
|
-
#endif
|
132
|
-
#ifndef RARRAY_CONST_PTR
|
133
|
-
#define RARRAY_CONST_PTR(a) RARRAY_PTR(a)
|
134
|
-
#endif
|
135
|
-
#ifndef RB_OBJ_WRITE
|
136
|
-
#define RB_OBJ_WRITE(a, slot, b) do {*(slot) = (b);} while (0)
|
137
|
-
#endif
|
138
|
-
#ifndef RB_OBJ_WRITTEN
|
139
|
-
#define RB_OBJ_WRITTEN(a, oldv, b) do {(void)oldv;} while (0)
|
140
|
-
#endif
|
141
|
-
|
142
|
-
/* new macros in ruby 2.4.0
|
143
|
-
*/
|
144
|
-
#ifndef ALWAYS_INLINE
|
145
|
-
#if defined(__GNUC__) && ((__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
146
|
-
/* gcc version >= 3.1 */
|
147
|
-
#define ALWAYS_INLINE(x) __attribute__((always_inline)) x
|
148
|
-
#endif
|
149
|
-
#ifdef _MSC_VER
|
150
|
-
/* microsoft c */
|
151
|
-
#define ALWAYS_INLINE(x) __forceinline x
|
152
|
-
#endif
|
153
|
-
#ifndef ALWAYS_INLINE
|
154
|
-
#define ALWAYS_INLINE(x) x
|
155
|
-
#endif
|
156
|
-
#endif /* ALWAYS_INLINE */
|
157
|
-
|
158
92
|
/* macros depends on the compiler.
|
159
93
|
* LIKELY(x) hint for the compiler that 'x' is 1(TRUE) in many cases.
|
160
94
|
* UNLIKELY(x) hint for the compiler that 'x' is 0(FALSE) in many cases.
|
@@ -316,6 +250,7 @@ typedef struct oci8_svcctx {
|
|
316
250
|
const oci8_logoff_strategy_t *logoff_strategy;
|
317
251
|
OCISession *usrhp;
|
318
252
|
OCIServer *srvhp;
|
253
|
+
ub4 server_version;
|
319
254
|
rb_pid_t pid;
|
320
255
|
unsigned char state;
|
321
256
|
char is_autocommit;
|
@@ -340,7 +275,8 @@ typedef struct {
|
|
340
275
|
} oci8_exec_sql_var_t;
|
341
276
|
|
342
277
|
#define oci8_raise(err, status, stmt) oci8_do_raise(err, status, stmt, __FILE__, __LINE__)
|
343
|
-
#define oci8_env_raise(
|
278
|
+
#define oci8_env_raise(env, status) oci8_do_env_raise(env, status, 0, __FILE__, __LINE__)
|
279
|
+
#define oci8_env_free_and_raise(env, status) oci8_do_env_raise(env, status, 1, __FILE__, __LINE__)
|
344
280
|
#define oci8_raise_init_error() oci8_do_raise_init_error(__FILE__, __LINE__)
|
345
281
|
#define oci8_raise_by_msgno(msgno, default_msg) oci8_do_raise_by_msgno(msgno, default_msg, __FILE__, __LINE__)
|
346
282
|
|
@@ -364,7 +300,7 @@ OCIEnv *oci8_make_envhp(void);
|
|
364
300
|
extern oci8_tls_key_t oci8_tls_key; /* native thread key */
|
365
301
|
OCIError *oci8_make_errhp(void);
|
366
302
|
|
367
|
-
static inline OCIError *oci8_get_errhp()
|
303
|
+
static inline OCIError *oci8_get_errhp(void)
|
368
304
|
{
|
369
305
|
OCIError *errhp = (OCIError *)oci8_tls_get(oci8_tls_key);
|
370
306
|
return LIKELY(errhp != NULL) ? errhp : oci8_make_errhp();
|
@@ -406,7 +342,8 @@ void *oci8_check_typeddata(VALUE obj, const oci8_handle_data_type_t *data_type,
|
|
406
342
|
extern VALUE eOCIException;
|
407
343
|
extern VALUE eOCIBreak;
|
408
344
|
void Init_oci8_error(void);
|
409
|
-
NORETURN(void
|
345
|
+
NORETURN(void oci8_do_raise(OCIError *errhp, sword status, OCIStmt *stmthp, const char *file, int line));
|
346
|
+
NORETURN(void oci8_do_env_raise(OCIEnv *envhp, sword status, int free_envhp, const char *file, int line));
|
410
347
|
NORETURN(void oci8_do_raise_init_error(const char *file, int line));
|
411
348
|
sb4 oci8_get_error_code(OCIError *errhp);
|
412
349
|
VALUE oci8_get_error_message(ub4 msgno, const char *default_msg);
|
@@ -488,8 +425,8 @@ OCINumber *oci8_dbl_to_onum(OCINumber *result, double dbl, OCIError *errhp);
|
|
488
425
|
void Init_oci_datetime(void);
|
489
426
|
VALUE oci8_make_ocidate(OCIDate *od);
|
490
427
|
OCIDate *oci8_set_ocidate(OCIDate *od, VALUE val);
|
491
|
-
VALUE
|
492
|
-
OCIDateTime *
|
428
|
+
VALUE oci8_make_ocitimestamp(OCIDateTime *dttm, boolean have_tz);
|
429
|
+
OCIDateTime *oci8_set_ocitimestamp_tz(OCIDateTime *dttm, VALUE val, VALUE svc);
|
493
430
|
VALUE oci8_make_interval_ym(OCIInterval *s);
|
494
431
|
VALUE oci8_make_interval_ds(OCIInterval *s);
|
495
432
|
|
@@ -514,6 +451,13 @@ void Init_oci8_win32(VALUE cOCI8);
|
|
514
451
|
/* hook_funcs.c */
|
515
452
|
void oci8_install_hook_functions(void);
|
516
453
|
void oci8_shutdown_sockets(void);
|
454
|
+
#ifdef HAVE_PLTHOOK
|
455
|
+
extern int oci8_cancel_read_at_exit;
|
456
|
+
extern int oci8_tcp_keepalive_time;
|
457
|
+
#else
|
458
|
+
#define oci8_cancel_read_at_exit (-1)
|
459
|
+
#define oci8_tcp_keepalive_time (-1)
|
460
|
+
#endif
|
517
461
|
|
518
462
|
#define OCI8StringValue(v) do { \
|
519
463
|
StringValue(v); \
|
data/ext/oci8/oci8lib.c
CHANGED
@@ -7,6 +7,10 @@
|
|
7
7
|
#ifdef HAVE_RUBY_THREAD_H
|
8
8
|
#include <ruby/thread.h>
|
9
9
|
#endif
|
10
|
+
#if defined(HAVE_PLTHOOK) && !defined(WIN32)
|
11
|
+
#include <dlfcn.h>
|
12
|
+
#include "plthook.h"
|
13
|
+
#endif
|
10
14
|
|
11
15
|
ID oci8_id_at_last_error;
|
12
16
|
ID oci8_id_get;
|
@@ -67,14 +71,130 @@ static VALUE bind_base_alloc(VALUE klass)
|
|
67
71
|
rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(klass));
|
68
72
|
}
|
69
73
|
|
74
|
+
#if defined(HAVE_PLTHOOK) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(TRUFFLERUBY)
|
75
|
+
static const char *find_libclntsh(void *handle)
|
76
|
+
{
|
77
|
+
void *symaddr = dlsym(handle, "OCIEnvCreate");
|
78
|
+
Dl_info info;
|
79
|
+
#ifdef __APPLE__
|
80
|
+
const char *basename = "libclntsh.dylib";
|
81
|
+
#else
|
82
|
+
const char *basename = "libclntsh.so";
|
83
|
+
#endif
|
84
|
+
const char *p;
|
85
|
+
|
86
|
+
if (symaddr == NULL) {
|
87
|
+
return NULL;
|
88
|
+
}
|
89
|
+
if (dladdr(symaddr, &info) == 0) {
|
90
|
+
return NULL;
|
91
|
+
}
|
92
|
+
if ((p = strrchr(info.dli_fname, '/')) == NULL) {
|
93
|
+
return NULL;
|
94
|
+
}
|
95
|
+
if (strncmp(p + 1, basename, strlen(basename)) != 0) {
|
96
|
+
return NULL;
|
97
|
+
}
|
98
|
+
return info.dli_fname;
|
99
|
+
}
|
100
|
+
|
101
|
+
/*
|
102
|
+
* Symbol prefix depends on the platform.
|
103
|
+
* Linux x86_64 - no prefix
|
104
|
+
* Linux x86_32 - "_"
|
105
|
+
* macOS - "@_"
|
106
|
+
*/
|
107
|
+
static const char *find_symbol_prefix(plthook_t *ph, size_t *len)
|
108
|
+
{
|
109
|
+
unsigned int pos = 0;
|
110
|
+
const char *name;
|
111
|
+
void **addr;
|
112
|
+
|
113
|
+
while (plthook_enum(ph, &pos, &name, &addr) == 0) {
|
114
|
+
const char *p = strstr(name, "OCIEnvCreate");
|
115
|
+
if (p != NULL) {
|
116
|
+
*len = p - name;
|
117
|
+
return name;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
return NULL;
|
121
|
+
}
|
122
|
+
|
123
|
+
/*
|
124
|
+
* Fix PLT entries against function interposition.
|
125
|
+
* See: http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/ldap-auth-and-function-interposition.md
|
126
|
+
*/
|
127
|
+
static void rebind_internal_symbols(void)
|
128
|
+
{
|
129
|
+
const char *libfile;
|
130
|
+
void *handle;
|
131
|
+
int flags = RTLD_LAZY | RTLD_NOLOAD;
|
132
|
+
plthook_t *ph;
|
133
|
+
unsigned int pos = 0;
|
134
|
+
const char *name;
|
135
|
+
void **addr;
|
136
|
+
const char *prefix;
|
137
|
+
size_t prefix_len;
|
138
|
+
|
139
|
+
#ifdef RTLD_FIRST
|
140
|
+
flags |= RTLD_FIRST; /* for macOS */
|
141
|
+
#endif
|
142
|
+
|
143
|
+
libfile = find_libclntsh(RTLD_DEFAULT); /* normal case */
|
144
|
+
if (libfile == NULL) {
|
145
|
+
libfile = find_libclntsh(RTLD_NEXT); /* special case when OCIEnvCreate is hooked by LD_PRELOAD */
|
146
|
+
}
|
147
|
+
if (libfile == NULL) {
|
148
|
+
return;
|
149
|
+
}
|
150
|
+
handle = dlopen(libfile, flags);
|
151
|
+
if (handle == NULL) {
|
152
|
+
return;
|
153
|
+
}
|
154
|
+
if (plthook_open(&ph, libfile) != 0) {
|
155
|
+
dlclose(handle);
|
156
|
+
return;
|
157
|
+
}
|
158
|
+
prefix = find_symbol_prefix(ph, &prefix_len);
|
159
|
+
if (prefix == NULL) {
|
160
|
+
dlclose(handle);
|
161
|
+
plthook_close(ph);
|
162
|
+
return;
|
163
|
+
}
|
164
|
+
while (plthook_enum(ph, &pos, &name, &addr) == 0) {
|
165
|
+
void *funcaddr;
|
166
|
+
if (prefix_len != 0) {
|
167
|
+
if (strncmp(name, prefix, prefix_len) != 0) {
|
168
|
+
continue;
|
169
|
+
}
|
170
|
+
name += prefix_len;
|
171
|
+
}
|
172
|
+
if (strncmp(name, "OCI", 3) == 0) {
|
173
|
+
/* exclude functions starting with OCI not to prevent LD_PRELOAD hooking */
|
174
|
+
continue;
|
175
|
+
}
|
176
|
+
funcaddr = dlsym(handle, name);
|
177
|
+
if (funcaddr != NULL && *addr != funcaddr) {
|
178
|
+
/* If libclntsh.so exports and imports same functions, their
|
179
|
+
* PLT entries are forcedly modified to point to itself not
|
180
|
+
* to use functions in other libraries.
|
181
|
+
*/
|
182
|
+
*addr = funcaddr;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
plthook_close(ph);
|
186
|
+
dlclose(handle);
|
187
|
+
}
|
188
|
+
#endif
|
189
|
+
|
70
190
|
#ifdef _WIN32
|
71
191
|
__declspec(dllexport)
|
72
192
|
#endif
|
73
193
|
void
|
74
|
-
Init_oci8lib()
|
194
|
+
Init_oci8lib(void)
|
75
195
|
{
|
76
196
|
VALUE cOCI8;
|
77
|
-
OCIEnv *envhp;
|
197
|
+
OCIEnv *envhp = NULL;
|
78
198
|
OCIError *errhp;
|
79
199
|
sword rv;
|
80
200
|
|
@@ -106,6 +226,9 @@ Init_oci8lib()
|
|
106
226
|
oracle_client_version = ORAVERNUM(major, minor, update, patch, port_update);
|
107
227
|
}
|
108
228
|
#endif
|
229
|
+
#if defined(HAVE_PLTHOOK) && !defined(WIN32) && !defined(__CYGWIN__) && !defined(TRUFFLERUBY)
|
230
|
+
rebind_internal_symbols();
|
231
|
+
#endif
|
109
232
|
|
110
233
|
oci8_id_at_last_error = rb_intern("@last_error");
|
111
234
|
oci8_id_get = rb_intern("get");
|
@@ -153,7 +276,11 @@ Init_oci8lib()
|
|
153
276
|
/* allocate a temporary errhp to pass Init_oci_number() */
|
154
277
|
rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
|
155
278
|
if (rv != OCI_SUCCESS) {
|
156
|
-
|
279
|
+
if (envhp != NULL) {
|
280
|
+
oci8_env_free_and_raise(envhp, rv);
|
281
|
+
} else {
|
282
|
+
oci8_raise_init_error();
|
283
|
+
}
|
157
284
|
}
|
158
285
|
rv = OCIHandleAlloc(envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
|
159
286
|
if (rv != OCI_SUCCESS)
|
@@ -334,6 +461,7 @@ sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *
|
|
334
461
|
parg.func = func;
|
335
462
|
parg.data = data;
|
336
463
|
rv = (sword)rb_protect(protected_call, (VALUE)&parg, &state);
|
464
|
+
RB_OBJ_WRITE(svcctx->base.self, &svcctx->executing_thread, Qnil);
|
337
465
|
if (state) {
|
338
466
|
rb_jump_tag(state);
|
339
467
|
}
|
@@ -354,8 +482,8 @@ typedef struct {
|
|
354
482
|
OCIStmt *stmtp;
|
355
483
|
} cb_arg_t;
|
356
484
|
|
357
|
-
static VALUE exec_sql(
|
358
|
-
static VALUE ensure_func(
|
485
|
+
static VALUE exec_sql(VALUE varg);
|
486
|
+
static VALUE ensure_func(VALUE varg);
|
359
487
|
|
360
488
|
/*
|
361
489
|
* utility function to execute a single SQL statement
|
@@ -376,13 +504,14 @@ sword oci8_exec_sql(oci8_svcctx_t *svcctx, const char *sql_text, ub4 num_define_
|
|
376
504
|
return (sword)rb_ensure(exec_sql, (VALUE)&arg, ensure_func, (VALUE)&arg);
|
377
505
|
}
|
378
506
|
|
379
|
-
static VALUE exec_sql(
|
507
|
+
static VALUE exec_sql(VALUE varg)
|
380
508
|
{
|
509
|
+
cb_arg_t *arg = (cb_arg_t *)varg;
|
381
510
|
ub4 pos;
|
382
511
|
sword rv;
|
383
512
|
|
384
513
|
chker2(OCIStmtPrepare2(arg->svcctx->base.hp.svc, &arg->stmtp, oci8_errhp,
|
385
|
-
(text*)arg->sql_text, strlen(arg->sql_text), NULL, 0,
|
514
|
+
(text*)arg->sql_text, (ub4)strlen(arg->sql_text), NULL, 0,
|
386
515
|
OCI_NTV_SYNTAX, OCI_DEFAULT),
|
387
516
|
&arg->svcctx->base);
|
388
517
|
for (pos = 0; pos < arg->num_define_vars; pos++) {
|
@@ -419,8 +548,9 @@ static VALUE exec_sql(cb_arg_t *arg)
|
|
419
548
|
return (VALUE)rv;
|
420
549
|
}
|
421
550
|
|
422
|
-
static VALUE ensure_func(
|
551
|
+
static VALUE ensure_func(VALUE varg)
|
423
552
|
{
|
553
|
+
cb_arg_t *arg = (cb_arg_t *)varg;
|
424
554
|
if (arg->stmtp != NULL) {
|
425
555
|
OCIStmtRelease(arg->stmtp, oci8_errhp, NULL, 0, OCI_DEFAULT);
|
426
556
|
}
|
@@ -431,6 +561,24 @@ static VALUE ensure_func(cb_arg_t *arg)
|
|
431
561
|
|
432
562
|
#ifndef _WIN32
|
433
563
|
#include <dlfcn.h>
|
564
|
+
static void *load_file(const char *filename, int flags, VALUE errors)
|
565
|
+
{
|
566
|
+
void *handle = dlopen(filename, flags);
|
567
|
+
|
568
|
+
if (handle == NULL) {
|
569
|
+
char *err = dlerror();
|
570
|
+
VALUE msg;
|
571
|
+
|
572
|
+
if (strstr(err, filename) == NULL) {
|
573
|
+
msg = rb_sprintf("%s: %s", filename, err);
|
574
|
+
msg = rb_enc_associate_index(msg, rb_locale_encindex());
|
575
|
+
} else {
|
576
|
+
msg = rb_locale_str_new_cstr(err);
|
577
|
+
}
|
578
|
+
rb_ary_push(errors, msg);
|
579
|
+
}
|
580
|
+
return handle;
|
581
|
+
}
|
434
582
|
#endif
|
435
583
|
|
436
584
|
void *oci8_find_symbol(const char *symbol_name)
|
@@ -473,58 +621,50 @@ void *oci8_find_symbol(const char *symbol_name)
|
|
473
621
|
"libclntsh.sl.12.1",
|
474
622
|
"libclntsh.sl.11.1",
|
475
623
|
"libclntsh.sl.10.1",
|
476
|
-
"libclntsh.sl.9.0",
|
477
|
-
"libclntsh.sl.8.0",
|
478
624
|
#elif defined(__APPLE__)
|
479
625
|
/* Mac OS X */
|
626
|
+
"libclntsh.dylib",
|
480
627
|
"libclntsh.dylib.12.1",
|
481
628
|
"libclntsh.dylib.11.1",
|
482
629
|
"libclntsh.dylib.10.1",
|
483
630
|
#else
|
484
631
|
/* Linux, Solaris and HP-UX(IA64) */
|
632
|
+
"libclntsh.so",
|
485
633
|
"libclntsh.so.12.1",
|
486
634
|
"libclntsh.so.11.1",
|
487
635
|
"libclntsh.so.10.1",
|
488
|
-
"libclntsh.so.9.0",
|
489
|
-
"libclntsh.so.8.0",
|
490
636
|
#endif
|
491
637
|
};
|
492
638
|
#define NUM_SONAMES (sizeof(sonames)/sizeof(sonames[0]))
|
639
|
+
#if defined(_AIX) /* AIX */
|
640
|
+
#define BASE_SONAME "libclntsh.a(shr.o)"
|
641
|
+
#elif defined(__hppa) /* HP-UX(PA-RISC) */
|
642
|
+
#define BASE_SONAME "libclntsh.sl"
|
643
|
+
#elif !defined(__CYGWIN__) && !defined(__APPLE__)
|
644
|
+
#define BASE_SONAME "libclntsh.so"
|
645
|
+
#endif
|
493
646
|
size_t idx;
|
494
|
-
|
647
|
+
VALUE err = rb_ary_new();
|
495
648
|
|
496
649
|
#ifdef _AIX
|
497
650
|
#define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL|RTLD_MEMBER)
|
498
651
|
#else
|
499
652
|
#define DLOPEN_FLAG (RTLD_LAZY|RTLD_GLOBAL)
|
500
653
|
#endif
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
654
|
+
#ifdef BASE_SONAME
|
655
|
+
char *oracle_home = getenv("ORACLE_HOME");
|
656
|
+
|
657
|
+
if (oracle_home != NULL) {
|
658
|
+
VALUE fname = rb_str_buf_cat2(rb_str_buf_new_cstr(oracle_home), "/lib/" BASE_SONAME);
|
659
|
+
handle = load_file(StringValueCStr(fname), DLOPEN_FLAG, err);
|
660
|
+
RB_GC_GUARD(fname);
|
661
|
+
}
|
662
|
+
#endif
|
663
|
+
for (idx = 0; handle == NULL && idx < NUM_SONAMES; idx++) {
|
664
|
+
handle = load_file(sonames[idx], DLOPEN_FLAG, err);
|
507
665
|
}
|
508
666
|
if (handle == NULL) {
|
509
|
-
VALUE msg;
|
510
|
-
const VALUE *arr = RARRAY_CONST_PTR(err);
|
511
|
-
|
512
|
-
msg = rb_str_buf_new(NUM_SONAMES * 50);
|
513
|
-
for (idx = 0; idx < NUM_SONAMES; idx++) {
|
514
|
-
const char *errmsg = RSTRING_PTR(arr[idx]);
|
515
|
-
if (idx != 0) {
|
516
|
-
rb_str_buf_cat2(msg, " ");
|
517
|
-
}
|
518
|
-
if (strstr(errmsg, sonames[idx]) == NULL) {
|
519
|
-
/* prepend "soname: " if soname is not found in
|
520
|
-
* the error message.
|
521
|
-
*/
|
522
|
-
rb_str_buf_cat2(msg, sonames[idx]);
|
523
|
-
rb_str_buf_cat2(msg, ": ");
|
524
|
-
}
|
525
|
-
rb_str_buf_append(msg, arr[idx]);
|
526
|
-
rb_str_buf_cat2(msg, ";");
|
527
|
-
}
|
667
|
+
VALUE msg = rb_ary_join(err, rb_usascii_str_new_cstr("; "));
|
528
668
|
rb_exc_raise(rb_exc_new3(rb_eLoadError, msg));
|
529
669
|
}
|
530
670
|
}
|