ruby-oci8 2.2.3 → 2.2.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|