ruby-oci8 2.0.1 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +89 -0
- data/Makefile +16 -14
- data/NEWS +36 -0
- data/VERSION +1 -1
- data/dist-files +3 -0
- data/ext/oci8/apiwrap.yml +107 -95
- data/ext/oci8/attr.c +14 -13
- data/ext/oci8/bind.c +4 -4
- data/ext/oci8/encoding.c +1 -1
- data/ext/oci8/env.c +72 -22
- data/ext/oci8/error.c +1 -1
- data/ext/oci8/extconf.rb +8 -2
- data/ext/oci8/lob.c +24 -5
- data/ext/oci8/metadata.c +3 -3
- data/ext/oci8/object.c +10 -5
- data/ext/oci8/oci8.c +87 -2
- data/ext/oci8/oci8.h +70 -16
- data/ext/oci8/oci8lib.c +37 -3
- data/ext/oci8/ocidatetime.c +1 -1
- data/ext/oci8/ocinumber.c +262 -148
- data/ext/oci8/oraconf.rb +63 -63
- data/ext/oci8/oradate.c +1 -1
- data/lib/dbd/OCI8.rb +17 -2
- data/lib/oci8.rb.in +1 -0
- data/lib/oci8/bindtype.rb +295 -0
- data/lib/oci8/oci8.rb +23 -270
- data/test/test_all.rb +12 -3
- data/test/test_appinfo.rb +29 -0
- data/test/test_dbi.rb +1 -1
- data/test/test_encoding.rb +100 -0
- data/test/test_oci8.rb +37 -0
- data/test/test_oranumber.rb +24 -0
- metadata +6 -3
data/ext/oci8/attr.c
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
* attr.c
|
4
4
|
*
|
5
5
|
* $Author: kubo $
|
6
|
-
* $Date: 2009-
|
6
|
+
* $Date: 2009-05-17 22:07:16 +0900 (Sun, 17 May 2009) $
|
7
7
|
*
|
8
8
|
* Copyright (C) 2002-2007 KUBO Takehiro <kubo@jiubao.org>
|
9
9
|
*/
|
@@ -106,7 +106,8 @@ static VALUE get_rowid_attr(rowid_arg_t *arg)
|
|
106
106
|
* Oracle Server.
|
107
107
|
*/
|
108
108
|
oci8_base_t *svc;
|
109
|
-
oci8_exec_sql_var_t
|
109
|
+
oci8_exec_sql_var_t define_var;
|
110
|
+
oci8_exec_sql_var_t bind_var;
|
110
111
|
|
111
112
|
/* search a connection from the handle */
|
112
113
|
svc = base;
|
@@ -117,19 +118,19 @@ static VALUE get_rowid_attr(rowid_arg_t *arg)
|
|
117
118
|
}
|
118
119
|
}
|
119
120
|
/* :strval */
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
define_var.valuep = buf;
|
122
|
+
define_var.value_sz = sizeof(buf);
|
123
|
+
define_var.dty = SQLT_CHR;
|
124
|
+
define_var.indp = NULL;
|
125
|
+
define_var.alenp = &buflen;
|
125
126
|
/* :rowid */
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
127
|
+
bind_var.valuep = &arg->ridp;
|
128
|
+
bind_var.value_sz = sizeof(void *);
|
129
|
+
bind_var.dty = SQLT_RDD;
|
130
|
+
bind_var.indp = NULL;
|
131
|
+
bind_var.alenp = NULL;
|
131
132
|
/* convert the rowid descriptor to a string value by querying Oracle server. */
|
132
|
-
oci8_exec_sql((oci8_svcctx_t*)svc, "
|
133
|
+
oci8_exec_sql((oci8_svcctx_t*)svc, "SELECT :rid FROM dual", 1, &define_var, 1, &bind_var, 1);
|
133
134
|
if (buflen == 0) {
|
134
135
|
return Qnil;
|
135
136
|
}
|
data/ext/oci8/bind.c
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
* bind.c
|
4
4
|
*
|
5
5
|
* $Author: kubo $
|
6
|
-
* $Date: 2009-
|
6
|
+
* $Date: 2009-05-17 22:07:16 +0900 (Sun, 17 May 2009) $
|
7
7
|
*
|
8
8
|
* Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
|
9
9
|
*/
|
@@ -46,7 +46,7 @@ static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE len
|
|
46
46
|
} else {
|
47
47
|
sz = NUM2INT(length);
|
48
48
|
}
|
49
|
-
if (sz
|
49
|
+
if (sz < 0) {
|
50
50
|
rb_raise(rb_eArgError, "invalid bind length %d", sz);
|
51
51
|
}
|
52
52
|
sz += sizeof(sb4);
|
@@ -284,8 +284,8 @@ static VALUE bind_float_get(oci8_bind_t *obind, void *data, void *null_struct)
|
|
284
284
|
|
285
285
|
static void bind_float_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
286
286
|
{
|
287
|
-
|
288
|
-
*(double*)data = RFLOAT_VALUE(val);
|
287
|
+
/* val is converted to Float if it isn't Float. */
|
288
|
+
*(double*)data = RFLOAT_VALUE(rb_Float(val));
|
289
289
|
}
|
290
290
|
|
291
291
|
static void bind_float_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
|
data/ext/oci8/encoding.c
CHANGED
@@ -45,7 +45,7 @@ VALUE oci8_charset_id2name(VALUE svc, VALUE csid)
|
|
45
45
|
char buf[OCI_NLS_MAXBUFSZ];
|
46
46
|
sword rv;
|
47
47
|
|
48
|
-
rv = OCINlsCharSetIdToName(oci8_envhp, TO_ORATEXT(buf), sizeof(buf), FIX2INT(csid));
|
48
|
+
rv = OCINlsCharSetIdToName(oci8_envhp, TO_ORATEXT(buf), sizeof(buf), (ub2)FIX2INT(csid));
|
49
49
|
if (rv != OCI_SUCCESS) {
|
50
50
|
return Qnil;
|
51
51
|
}
|
data/ext/oci8/env.c
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
2
|
/*
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
*/
|
3
|
+
* env.c - part of ruby-oci8
|
4
|
+
*
|
5
|
+
* Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
|
6
|
+
*/
|
8
7
|
#include "oci8.h"
|
9
8
|
|
10
9
|
#if !defined(RUBY_VM)
|
@@ -12,7 +11,37 @@
|
|
12
11
|
#include <util.h>
|
13
12
|
#endif
|
14
13
|
|
15
|
-
|
14
|
+
#ifdef _WIN32
|
15
|
+
#ifdef HAVE_RUBY_WIN32_H
|
16
|
+
#include <ruby/win32.h> /* for rb_w32_getenv() */
|
17
|
+
#else
|
18
|
+
#include <win32/win32.h> /* for rb_w32_getenv() */
|
19
|
+
#endif
|
20
|
+
#endif
|
21
|
+
|
22
|
+
#ifdef HAVE_RUBY_UTIL_H
|
23
|
+
#include <ruby/util.h>
|
24
|
+
#endif
|
25
|
+
|
26
|
+
#ifdef RUBY_VM
|
27
|
+
ub4 oci8_env_mode = OCI_OBJECT | OCI_THREADED;
|
28
|
+
#else
|
29
|
+
ub4 oci8_env_mode = OCI_OBJECT;
|
30
|
+
#endif
|
31
|
+
|
32
|
+
OCIEnv *oci8_global_envhp;
|
33
|
+
|
34
|
+
OCIEnv *oci8_make_envhp(void)
|
35
|
+
{
|
36
|
+
sword rv;
|
37
|
+
|
38
|
+
rv = OCIEnvCreate(&oci8_global_envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
|
39
|
+
if (rv != OCI_SUCCESS) {
|
40
|
+
oci8_raise_init_error();
|
41
|
+
}
|
42
|
+
return oci8_global_envhp;
|
43
|
+
}
|
44
|
+
|
16
45
|
#ifdef RUBY_VM
|
17
46
|
/*
|
18
47
|
* oci8_errhp is a thread local object in ruby 1.9.
|
@@ -53,17 +82,23 @@ OCIError *oci8_make_errhp(void)
|
|
53
82
|
/*
|
54
83
|
* oci8_errhp is global in ruby 1.8.
|
55
84
|
*/
|
56
|
-
OCIError *
|
85
|
+
OCIError *oci8_global_errhp;
|
86
|
+
|
87
|
+
OCIError *oci8_make_errhp(void)
|
88
|
+
{
|
89
|
+
sword rv;
|
90
|
+
|
91
|
+
rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_global_errhp, OCI_HTYPE_ERROR, 0, NULL);
|
92
|
+
if (rv != OCI_SUCCESS)
|
93
|
+
oci8_env_raise(oci8_envhp, rv);
|
94
|
+
return oci8_global_errhp;
|
95
|
+
}
|
57
96
|
#endif
|
58
97
|
|
59
98
|
void Init_oci8_env(void)
|
60
99
|
{
|
61
|
-
sword rv;
|
62
100
|
#ifdef RUBY_VM
|
63
|
-
ub4 mode = OCI_OBJECT | OCI_THREADED;
|
64
101
|
int error;
|
65
|
-
#else
|
66
|
-
ub4 mode = OCI_OBJECT;
|
67
102
|
#endif
|
68
103
|
|
69
104
|
#if !defined(RUBY_VM) && !defined(_WIN32)
|
@@ -85,23 +120,38 @@ void Init_oci8_env(void)
|
|
85
120
|
}
|
86
121
|
}
|
87
122
|
#endif /* WIN32 */
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
123
|
+
|
124
|
+
/* workaround code.
|
125
|
+
*
|
126
|
+
* When ORACLE_HOME ends with '/' and the Oracle client is
|
127
|
+
* an instant client lower than 10.2.0.3, OCIEvnCreate()
|
128
|
+
* doesn't work even though the combination of OCIInitialize()
|
129
|
+
* and OCIEnvInit() works fine. Delete the last slash for
|
130
|
+
* a workaround.
|
131
|
+
*/
|
132
|
+
if (oracle_client_version < ORAVERNUM(10, 2, 0, 3, 0)) {
|
133
|
+
#ifdef _WIN32
|
134
|
+
#define DIR_SEP '\\'
|
135
|
+
#else
|
136
|
+
#define DIR_SEP '/'
|
137
|
+
#endif
|
138
|
+
char *home = getenv("ORACLE_HOME");
|
139
|
+
if (home != NULL) {
|
140
|
+
size_t homelen = strlen(home);
|
141
|
+
if (homelen > 0 && home[homelen - 1] == DIR_SEP) {
|
142
|
+
home = ruby_strdup(home);
|
143
|
+
home[homelen - 1] = '\0';
|
144
|
+
ruby_setenv("ORACLE_HOME", home);
|
145
|
+
xfree(home);
|
146
|
+
}
|
147
|
+
}
|
95
148
|
}
|
149
|
+
|
96
150
|
#ifdef RUBY_VM
|
97
151
|
id_thread_key = rb_intern("__oci8_errhp__");
|
98
152
|
error = oci8_tls_key_init(&oci8_tls_key);
|
99
153
|
if (error != 0) {
|
100
154
|
rb_raise(rb_eRuntimeError, "Cannot create thread local key (errno = %d)", error);
|
101
155
|
}
|
102
|
-
#else /* RUBY_VM */
|
103
|
-
rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_errhp, OCI_HTYPE_ERROR, 0, NULL);
|
104
|
-
if (rv != OCI_SUCCESS)
|
105
|
-
oci8_env_raise(oci8_envhp, rv);
|
106
156
|
#endif
|
107
157
|
}
|
data/ext/oci8/error.c
CHANGED
@@ -157,7 +157,7 @@ static void set_backtrace_and_raise(VALUE exc, const char *file, int line)
|
|
157
157
|
#endif
|
158
158
|
backtrace = rb_funcall(rb_cObject, oci8_id_caller, 0);
|
159
159
|
if (TYPE(backtrace) == T_ARRAY) {
|
160
|
-
snprintf(errmsg, sizeof(errmsg), "%s:%d:in oci8lib
|
160
|
+
snprintf(errmsg, sizeof(errmsg), "%s:%d:in " STRINGIZE(oci8lib) DLEXT, file, line);
|
161
161
|
errmsg[sizeof(errmsg) - 1] = '\0';
|
162
162
|
rb_ary_unshift(backtrace, rb_usascii_str_new_cstr(errmsg));
|
163
163
|
rb_funcall(exc, oci8_id_set_backtrace, 1, backtrace);
|
data/ext/oci8/extconf.rb
CHANGED
@@ -61,7 +61,13 @@ funcs.keys.sort.each do |version|
|
|
61
61
|
puts "checking for Oracle #{verstr} API - #{result}"
|
62
62
|
break if result == 'fail'
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
|
+
have_type('oratext', 'ociap.h')
|
66
|
+
have_type('OCIDateTime*', 'ociap.h')
|
67
|
+
have_type('OCIInterval*', 'ociap.h')
|
68
|
+
have_type('OCICallbackLobRead2', 'ociap.h')
|
69
|
+
have_type('OCICallbackLobWrite2', 'ociap.h')
|
70
|
+
have_type('OCIAdmin*', 'ociap.h')
|
65
71
|
|
66
72
|
if with_config('oracle-version')
|
67
73
|
oci_client_version = with_config('oracle-version').to_i
|
@@ -97,7 +103,6 @@ have_func("localtime_r")
|
|
97
103
|
have_header("intern.h")
|
98
104
|
have_header("util.h")
|
99
105
|
# ruby 1.9 headers
|
100
|
-
have_header("ruby/util.h")
|
101
106
|
have_type('rb_encoding', ['ruby/ruby.h', 'ruby/encoding.h'])
|
102
107
|
|
103
108
|
# $! in C API
|
@@ -122,6 +127,7 @@ else
|
|
122
127
|
raise 'unsupported ruby version: ' + RUBY_VERSION
|
123
128
|
end
|
124
129
|
$defs << "-DInit_oci8lib=Init_#{so_basename}"
|
130
|
+
$defs << "-Doci8lib=#{so_basename}"
|
125
131
|
|
126
132
|
create_header()
|
127
133
|
|
data/ext/oci8/lob.c
CHANGED
@@ -26,6 +26,7 @@ typedef struct {
|
|
26
26
|
ub4 pos;
|
27
27
|
int char_width;
|
28
28
|
ub1 csfrm;
|
29
|
+
ub1 lobtype;
|
29
30
|
enum state state;
|
30
31
|
} oci8_lob_t;
|
31
32
|
|
@@ -149,6 +150,7 @@ static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm
|
|
149
150
|
lob->pos = 0;
|
150
151
|
lob->char_width = 1;
|
151
152
|
lob->csfrm = csfrm;
|
153
|
+
lob->lobtype = lobtype;
|
152
154
|
lob->state = S_NO_OPEN_CLOSE;
|
153
155
|
oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
|
154
156
|
if (!NIL_P(val)) {
|
@@ -360,8 +362,14 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
|
360
362
|
}
|
361
363
|
v = rb_ary_join(v, Qnil);
|
362
364
|
OBJ_TAINT(v);
|
363
|
-
|
364
|
-
|
365
|
+
if (lob->lobtype == OCI_TEMP_CLOB) {
|
366
|
+
/* set encoding */
|
367
|
+
rb_enc_associate(v, oci8_encoding);
|
368
|
+
return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
|
369
|
+
} else {
|
370
|
+
/* ASCII-8BIT */
|
371
|
+
return v;
|
372
|
+
}
|
365
373
|
}
|
366
374
|
|
367
375
|
static VALUE oci8_lob_write(VALUE self, VALUE data)
|
@@ -371,7 +379,11 @@ static VALUE oci8_lob_write(VALUE self, VALUE data)
|
|
371
379
|
ub4 amt;
|
372
380
|
|
373
381
|
lob_open(lob);
|
374
|
-
|
382
|
+
if (lob->lobtype == OCI_TEMP_CLOB) {
|
383
|
+
OCI8StringValue(data);
|
384
|
+
} else {
|
385
|
+
StringValue(data);
|
386
|
+
}
|
375
387
|
amt = RSTRING_LEN(data);
|
376
388
|
oci_lc(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm));
|
377
389
|
lob->pos += amt;
|
@@ -483,9 +495,15 @@ static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
|
|
483
495
|
oci8_lob_t *lob = DATA_PTR(self);
|
484
496
|
|
485
497
|
bfile_close(lob);
|
498
|
+
if (RSTRING_LEN(dir_alias) > UB2MAXVAL) {
|
499
|
+
rb_raise(rb_eRuntimeError, "dir_alias is too long.");
|
500
|
+
}
|
501
|
+
if (RSTRING_LEN(filename) > UB2MAXVAL) {
|
502
|
+
rb_raise(rb_eRuntimeError, "filename is too long.");
|
503
|
+
}
|
486
504
|
oci_lc(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob,
|
487
|
-
RSTRING_ORATEXT(dir_alias), RSTRING_LEN(dir_alias),
|
488
|
-
RSTRING_ORATEXT(filename), RSTRING_LEN(filename)));
|
505
|
+
RSTRING_ORATEXT(dir_alias), (ub2)RSTRING_LEN(dir_alias),
|
506
|
+
RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename)));
|
489
507
|
}
|
490
508
|
|
491
509
|
static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
|
@@ -503,6 +521,7 @@ static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
|
|
503
521
|
lob->pos = 0;
|
504
522
|
lob->char_width = 1;
|
505
523
|
lob->csfrm = SQLCS_IMPLICIT;
|
524
|
+
lob->lobtype = OCI_TEMP_BLOB;
|
506
525
|
lob->state = S_BFILE_CLOSE;
|
507
526
|
if (argc != 1) {
|
508
527
|
OCI8SafeStringValue(dir_alias);
|
data/ext/oci8/metadata.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
/*
|
3
3
|
* metadata.c
|
4
4
|
*
|
5
|
-
* Copyright (C) 2006-
|
5
|
+
* Copyright (C) 2006-2009 KUBO Takehiro <kubo@jiubao.org>
|
6
6
|
*
|
7
7
|
* implement private methods of classes in OCI8::Metadata module.
|
8
8
|
*
|
@@ -210,7 +210,7 @@ static VALUE metadata_get_oraint(VALUE self, VALUE idx)
|
|
210
210
|
memset(&on, 0, sizeof(on));
|
211
211
|
on.OCINumberPart[0] = size;
|
212
212
|
memcpy(&on.OCINumberPart[1], value, size);
|
213
|
-
return oci8_make_integer(&on);
|
213
|
+
return oci8_make_integer(&on, oci8_errhp);
|
214
214
|
}
|
215
215
|
|
216
216
|
static VALUE metadata_get_param(VALUE self, VALUE idx)
|
@@ -277,7 +277,7 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
|
|
277
277
|
oci_lc(OCIAttrSet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &val, 0, OCI_ATTR_DESC_PUBLIC, oci8_errhp));
|
278
278
|
}
|
279
279
|
oci_lc(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
|
280
|
-
objtype, OCI_DEFAULT, FIX2INT(type), desc->hp.dschp));
|
280
|
+
objtype, OCI_DEFAULT, (ub1)FIX2INT(type), desc->hp.dschp));
|
281
281
|
oci_lc(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp));
|
282
282
|
return oci8_metadata_create(parmhp, self, obj);
|
283
283
|
}
|
data/ext/oci8/object.c
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
2
|
/*
|
3
|
+
* Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
|
4
|
+
*/
|
5
|
+
|
6
|
+
/*
|
7
|
+
*
|
3
8
|
* Document-class: OCI8::TDO
|
4
9
|
*
|
5
10
|
* OCI8::TDO is the class for Type Descriptor Object, which describe
|
@@ -157,11 +162,11 @@ static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *dat
|
|
157
162
|
return rb_str_new(TO_CHARPTR(OCIRawPtr(oci8_envhp, *(OCIRaw **)data)),
|
158
163
|
OCIRawSize(oci8_envhp, *(OCIRaw **)data));
|
159
164
|
case ATTR_OCINUMBER:
|
160
|
-
return oci8_make_ocinumber((OCINumber *)data);
|
165
|
+
return oci8_make_ocinumber((OCINumber *)data, oci8_errhp);
|
161
166
|
case ATTR_FLOAT:
|
162
|
-
return oci8_make_float((OCINumber *)data);
|
167
|
+
return oci8_make_float((OCINumber *)data, oci8_errhp);
|
163
168
|
case ATTR_INTEGER:
|
164
|
-
return oci8_make_integer((OCINumber *)data);
|
169
|
+
return oci8_make_integer((OCINumber *)data, oci8_errhp);
|
165
170
|
case ATTR_BINARY_DOUBLE:
|
166
171
|
return rb_float_new(*(double*)data);
|
167
172
|
case ATTR_BINARY_FLOAT:
|
@@ -431,10 +436,10 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
|
|
431
436
|
break;
|
432
437
|
case ATTR_OCINUMBER:
|
433
438
|
case ATTR_FLOAT:
|
434
|
-
oci8_set_ocinumber((OCINumber*)data, val);
|
439
|
+
oci8_set_ocinumber((OCINumber*)data, val, oci8_errhp);
|
435
440
|
break;
|
436
441
|
case ATTR_INTEGER:
|
437
|
-
oci8_set_integer((OCINumber*)data, val);
|
442
|
+
oci8_set_integer((OCINumber*)data, val, oci8_errhp);
|
438
443
|
break;
|
439
444
|
case ATTR_BINARY_DOUBLE:
|
440
445
|
*(double*)data = NUM2DBL(val);
|
data/ext/oci8/oci8.c
CHANGED
@@ -17,6 +17,10 @@ extern rb_pid_t rb_w32_getpid(void);
|
|
17
17
|
#endif
|
18
18
|
#endif
|
19
19
|
|
20
|
+
#ifndef OCI_ATTR_CLIENT_IDENTIFIER
|
21
|
+
#define OCI_ATTR_CLIENT_IDENTIFIER 278
|
22
|
+
#endif
|
23
|
+
|
20
24
|
/*
|
21
25
|
* Document-class: OCI8
|
22
26
|
*
|
@@ -538,11 +542,11 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
|
|
538
542
|
|
539
543
|
if (have_OCIServerRelease) {
|
540
544
|
/* Oracle 9i or later */
|
541
|
-
oci_lc(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), svcctx->base.type, &version));
|
545
|
+
oci_lc(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type, &version));
|
542
546
|
return UINT2NUM(version);
|
543
547
|
} else {
|
544
548
|
/* Oracle 8.x */
|
545
|
-
oci_lc(OCIServerVersion(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), svcctx->base.type));
|
549
|
+
oci_lc(OCIServerVersion(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type));
|
546
550
|
if ((p = strchr(buf, '.')) != NULL) {
|
547
551
|
unsigned int major, minor, update, patch, port_update;
|
548
552
|
while (p >= buf && *p != ' ') {
|
@@ -556,6 +560,85 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
|
|
556
560
|
}
|
557
561
|
}
|
558
562
|
|
563
|
+
/*
|
564
|
+
* call-seq:
|
565
|
+
* ping -> true or false
|
566
|
+
*
|
567
|
+
* Verifies that the Oracle connection is alive.
|
568
|
+
*
|
569
|
+
* OCI8#ping also can be used to flush all the pending OCI client-side calls
|
570
|
+
* to the server if any exist. See: OCI8#client_identifier=.
|
571
|
+
*
|
572
|
+
* For Oracle 10.2 client or upper, a dummy round trip call is made by a newly
|
573
|
+
* added OCI function in Oracle 10.2.
|
574
|
+
*
|
575
|
+
* For Oracle 10.1 client or lower, a simple PL/SQL block "BEGIN NULL; END;"
|
576
|
+
* is executed to make a round trip call.
|
577
|
+
*/
|
578
|
+
static VALUE oci8_ping(VALUE self)
|
579
|
+
{
|
580
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
|
581
|
+
sword rv;
|
582
|
+
|
583
|
+
if (have_OCIPing_nb) {
|
584
|
+
/* Oracle 10.2 or upper */
|
585
|
+
rv = OCIPing_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT);
|
586
|
+
} else {
|
587
|
+
/* Oracle 10.1 or lower */
|
588
|
+
rv = oci8_exec_sql(svcctx, "BEGIN NULL; END;", 0U, NULL, 0U, NULL, 0);
|
589
|
+
}
|
590
|
+
return rv == OCI_SUCCESS ? Qtrue : FALSE;
|
591
|
+
}
|
592
|
+
|
593
|
+
/*
|
594
|
+
* call-seq:
|
595
|
+
* client_identifier = string
|
596
|
+
*
|
597
|
+
* Sets the CLIENT_IDENTIFIER column in the V$SESSION dictionary view.
|
598
|
+
* This can be up to 64 bytes long. The first character should not be ':'.
|
599
|
+
*
|
600
|
+
* If the Oracle client is 9i or upper, the change is not reflected to the
|
601
|
+
* server immediately. It is postponed until the next round trip call for
|
602
|
+
* example OCI8#exec, OCI8#ping, etc.
|
603
|
+
*
|
604
|
+
* This call is equivalent to "DBMS_SESSION.SET_IDENTIFIER(client_id VARCHAR2);"
|
605
|
+
* and available when the server is Oracle 9i or upper.
|
606
|
+
*/
|
607
|
+
static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
608
|
+
{
|
609
|
+
OCISession *sess = oci8_get_oci_session(self);
|
610
|
+
char *ptr;
|
611
|
+
ub4 size;
|
612
|
+
|
613
|
+
if (!NIL_P(val)) {
|
614
|
+
OCI8SafeStringValue(val);
|
615
|
+
ptr = RSTRING_PTR(val);
|
616
|
+
size = RSTRING_LEN(val);
|
617
|
+
} else {
|
618
|
+
ptr = "";
|
619
|
+
size = 0;
|
620
|
+
}
|
621
|
+
if (oracle_client_version >= 900) {
|
622
|
+
if (size > 0 && ptr[0] == ':') {
|
623
|
+
rb_raise(rb_eArgError, "client identifier should not start with ':'.");
|
624
|
+
}
|
625
|
+
oci_lc(OCIAttrSet(sess, OCI_HTYPE_SESSION, ptr,
|
626
|
+
size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp));
|
627
|
+
} else {
|
628
|
+
oci8_exec_sql_var_t bind_vars[1];
|
629
|
+
|
630
|
+
/* :client_id */
|
631
|
+
bind_vars[0].valuep = ptr;
|
632
|
+
bind_vars[0].value_sz = size;
|
633
|
+
bind_vars[0].dty = SQLT_CHR;
|
634
|
+
bind_vars[0].indp = NULL;
|
635
|
+
bind_vars[0].alenp = NULL;
|
636
|
+
|
637
|
+
oci8_exec_sql(oci8_get_svcctx(self), "BEGIN DBMS_SESSION.SET_IDENTIFIER(:client_id); END;", 0, NULL, 1, bind_vars, 1);
|
638
|
+
}
|
639
|
+
return val;
|
640
|
+
}
|
641
|
+
|
559
642
|
VALUE Init_oci8(void)
|
560
643
|
{
|
561
644
|
cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_class);
|
@@ -589,6 +672,8 @@ VALUE Init_oci8(void)
|
|
589
672
|
rb_define_method(cOCI8, "break", oci8_break, 0);
|
590
673
|
rb_define_method(cOCI8, "prefetch_rows=", oci8_set_prefetch_rows, 1);
|
591
674
|
rb_define_private_method(cOCI8, "oracle_server_vernum", oci8_oracle_server_vernum, 0);
|
675
|
+
rb_define_method(cOCI8, "ping", oci8_ping, 0);
|
676
|
+
rb_define_method(cOCI8, "client_identifier=", oci8_set_client_identifier, 1);
|
592
677
|
return cOCI8;
|
593
678
|
}
|
594
679
|
|