ruby-oci8 1.0.2
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 +569 -0
- data/Makefile +51 -0
- data/NEWS +322 -0
- data/README +415 -0
- data/VERSION +1 -0
- data/dist-files +70 -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/MANIFEST +22 -0
- data/ext/oci8/attr.c +415 -0
- data/ext/oci8/bind.c +194 -0
- data/ext/oci8/const.c +165 -0
- data/ext/oci8/define.c +53 -0
- data/ext/oci8/describe.c +81 -0
- data/ext/oci8/descriptor.c +39 -0
- data/ext/oci8/env.c +276 -0
- data/ext/oci8/error.c +234 -0
- data/ext/oci8/extconf.rb +118 -0
- data/ext/oci8/handle.c +262 -0
- data/ext/oci8/lob.c +386 -0
- data/ext/oci8/oci8.c +137 -0
- data/ext/oci8/oci8.h +345 -0
- data/ext/oci8/ocinumber.c +117 -0
- data/ext/oci8/oraconf.rb +1026 -0
- data/ext/oci8/oradate.c +426 -0
- data/ext/oci8/oranumber.c +445 -0
- data/ext/oci8/param.c +37 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/server.c +182 -0
- data/ext/oci8/session.c +99 -0
- data/ext/oci8/stmt.c +624 -0
- data/ext/oci8/svcctx.c +229 -0
- data/lib/DBD/OCI8/OCI8.rb +549 -0
- data/lib/oci8.rb.in +1605 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +54 -0
- data/ruby-oci8.spec +62 -0
- data/setup.rb +1331 -0
- data/support/README +4 -0
- data/support/runit/assert.rb +281 -0
- data/support/runit/cui/testrunner.rb +101 -0
- data/support/runit/error.rb +4 -0
- data/support/runit/method_mappable.rb +20 -0
- data/support/runit/robserver.rb +25 -0
- data/support/runit/setuppable.rb +15 -0
- data/support/runit/teardownable.rb +16 -0
- data/support/runit/testcase.rb +113 -0
- data/support/runit/testfailure.rb +25 -0
- data/support/runit/testresult.rb +121 -0
- data/support/runit/testsuite.rb +43 -0
- data/support/runit/version.rb +3 -0
- data/test/README +4 -0
- data/test/config.rb +129 -0
- data/test/test_all.rb +43 -0
- data/test/test_bind_raw.rb +53 -0
- data/test/test_bind_time.rb +191 -0
- data/test/test_break.rb +81 -0
- data/test/test_clob.rb +101 -0
- data/test/test_connstr.rb +80 -0
- data/test/test_dbi.rb +317 -0
- data/test/test_dbi_clob.rb +56 -0
- data/test/test_describe.rb +137 -0
- data/test/test_metadata.rb +243 -0
- data/test/test_oci8.rb +273 -0
- data/test/test_oradate.rb +263 -0
- data/test/test_oranumber.rb +149 -0
- metadata +118 -0
data/ext/oci8/extconf.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
raise <<EOS if RUBY_VERSION.index("1.9") == 0
|
2
|
+
---------------------------------------------------
|
3
|
+
error message:
|
4
|
+
ruby-oci8 1.0 is not supported by ruby #{RUBY_VERSION}.
|
5
|
+
Use ruby-oci8 2.0 in SVN trunk.
|
6
|
+
---------------------------------------------------
|
7
|
+
EOS
|
8
|
+
|
9
|
+
begin
|
10
|
+
require 'mkmf'
|
11
|
+
rescue LoadError
|
12
|
+
if /linux/ =~ RUBY_PLATFORM
|
13
|
+
raise <<EOS
|
14
|
+
You need to install a ruby development package ruby-devel, ruby-dev or so.
|
15
|
+
EOS
|
16
|
+
end
|
17
|
+
raise
|
18
|
+
end
|
19
|
+
|
20
|
+
require File.dirname(__FILE__) + '/oraconf'
|
21
|
+
|
22
|
+
RUBY_OCI8_VERSION = open("#{File.dirname(__FILE__)}/../../VERSION") {|f| f.read}.chomp
|
23
|
+
|
24
|
+
oraconf = OraConf.get()
|
25
|
+
|
26
|
+
def replace_keyword(source, target, replace)
|
27
|
+
puts "creating #{target} from #{source}"
|
28
|
+
open(source, "rb") { |f|
|
29
|
+
buf = f.read
|
30
|
+
replace.each do |key, value|
|
31
|
+
buf.gsub!('@@' + key + '@@', value)
|
32
|
+
end
|
33
|
+
open(target, "wb") {|fw|
|
34
|
+
fw.write buf
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
$objs = ["oci8.o", "handle.o", "const.o", "env.o", "error.o", "svcctx.o",
|
40
|
+
"server.o", "session.o", "stmt.o", "define.o", "bind.o",
|
41
|
+
"describe.o", "descriptor.o", "param.o", "lob.o",
|
42
|
+
"oradate.o", "oranumber.o", "ocinumber.o", "attr.o"]
|
43
|
+
|
44
|
+
$CFLAGS += oraconf.cflags
|
45
|
+
$libs += oraconf.libs
|
46
|
+
|
47
|
+
# OCIEnvCreate
|
48
|
+
# 8.0.5 - NG
|
49
|
+
# 9.0.1 - OK
|
50
|
+
have_func("OCIEnvCreate")
|
51
|
+
|
52
|
+
# OCITerminate
|
53
|
+
# 8.0.5 - NG
|
54
|
+
# 9.0.1 - OK
|
55
|
+
have_func("OCITerminate")
|
56
|
+
|
57
|
+
# OCIServerRelease
|
58
|
+
# 8.1.5 - NG
|
59
|
+
# 8.1.7 - OK
|
60
|
+
#have_func("OCIServerRelease")
|
61
|
+
|
62
|
+
# OCILobOpen
|
63
|
+
# 8.0.5 - NG
|
64
|
+
# 9.0.1 - OK
|
65
|
+
have_func("OCILobOpen")
|
66
|
+
|
67
|
+
# OCILobClose
|
68
|
+
# 8.0.5 - NG
|
69
|
+
# 9.0.1 - OK
|
70
|
+
have_func("OCILobClose")
|
71
|
+
|
72
|
+
# OCILobCreateTemporary
|
73
|
+
# 8.0.5 - NG
|
74
|
+
# 8.1.5 - OK
|
75
|
+
have_func("OCILobCreateTemporary")
|
76
|
+
|
77
|
+
have_func("OCILobGetChunkSize")
|
78
|
+
have_func("OCILobLocatorAssign")
|
79
|
+
|
80
|
+
$defs.push("-DHAVE_OCIRESET") unless /80./ =~ oraconf.version
|
81
|
+
|
82
|
+
# Checking gcc or not
|
83
|
+
if oraconf.cc_is_gcc
|
84
|
+
$CFLAGS += " -Wall"
|
85
|
+
end
|
86
|
+
|
87
|
+
# replace files
|
88
|
+
replace = {
|
89
|
+
'OCI8_CLIENT_VERSION' => oraconf.version,
|
90
|
+
'OCI8_MODULE_VERSION' => RUBY_OCI8_VERSION
|
91
|
+
}
|
92
|
+
|
93
|
+
# make ruby script before running create_makefile.
|
94
|
+
replace_keyword(File.dirname(__FILE__) + '/../../lib/oci8.rb.in', '../../lib/oci8.rb', replace)
|
95
|
+
|
96
|
+
create_header()
|
97
|
+
$defs = []
|
98
|
+
|
99
|
+
# make dependency file
|
100
|
+
open("depend", "w") do |f|
|
101
|
+
f.puts("Makefile: extconf.rb oraconf.rb")
|
102
|
+
f.puts("\t$(RUBY) extconf.rb")
|
103
|
+
$objs.each do |obj|
|
104
|
+
f.puts("#{obj}: $(srcdir)/#{obj.sub(/\.o$/, ".c")} $(srcdir)/oci8.h Makefile")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
create_makefile("oci8lib")
|
110
|
+
|
111
|
+
# append version info to extconf.h
|
112
|
+
open("extconf.h", "a") do |f|
|
113
|
+
replace.each do |key, value|
|
114
|
+
f.puts("#define #{key} \"#{value}\"")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
exit 0
|
data/ext/oci8/handle.c
ADDED
@@ -0,0 +1,262 @@
|
|
1
|
+
/*
|
2
|
+
handle.c - part of ruby-oci8
|
3
|
+
|
4
|
+
Copyright (C) 2002-2006 KUBO Takehiro <kubo@jiubao.org>
|
5
|
+
|
6
|
+
=begin
|
7
|
+
== OCIHandle
|
8
|
+
This is the abstract super class of OCI Handles.
|
9
|
+
See ((<Class Hierarchy>)).
|
10
|
+
=end
|
11
|
+
*/
|
12
|
+
#include "oci8.h"
|
13
|
+
|
14
|
+
static void oci8_handle_do_free(oci8_handle_t *h)
|
15
|
+
{
|
16
|
+
int i;
|
17
|
+
if (h->type == 0) {
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
/* free its children recursively.*/
|
21
|
+
for (i = 0;i < h->size;i++) {
|
22
|
+
if (h->children[i] != NULL)
|
23
|
+
oci8_handle_do_free(h->children[i]);
|
24
|
+
}
|
25
|
+
xfree(h->children);
|
26
|
+
/* unlink from parent */
|
27
|
+
oci8_unlink(h);
|
28
|
+
/* do free */
|
29
|
+
if (h->hp != NULL) {
|
30
|
+
if (h->type >= OCI_DTYPE_FIRST)
|
31
|
+
OCIDescriptorFree(h->hp, h->type);
|
32
|
+
else
|
33
|
+
OCIHandleFree(h->hp, h->type);
|
34
|
+
}
|
35
|
+
h->type = 0;
|
36
|
+
return;
|
37
|
+
}
|
38
|
+
|
39
|
+
/*
|
40
|
+
=begin
|
41
|
+
--- OCIHandle#attrSet(type, value)
|
42
|
+
:type
|
43
|
+
the type of attribute to be set.
|
44
|
+
See ((<Attributes of Handles and Descriptors>)).
|
45
|
+
:value
|
46
|
+
depends on ((|type|)).
|
47
|
+
|
48
|
+
correspond native OCI function: ((|OCIAttrSet|))
|
49
|
+
=end
|
50
|
+
*/
|
51
|
+
|
52
|
+
|
53
|
+
/*
|
54
|
+
=begin
|
55
|
+
--- OCIHandle#attrGet(type)
|
56
|
+
:type
|
57
|
+
the type of attribute.
|
58
|
+
See also ((<Attributes of Handles and Descriptors>)).
|
59
|
+
:return value
|
60
|
+
depends on ((|type|)).
|
61
|
+
|
62
|
+
correspond native OCI function: ((|OCIAttrGet|))
|
63
|
+
=end
|
64
|
+
*/
|
65
|
+
|
66
|
+
|
67
|
+
/*
|
68
|
+
=begin
|
69
|
+
--- OCIHandle#free()
|
70
|
+
explicitly free the OCI's data structure.
|
71
|
+
|
72
|
+
correspond native OCI function: ((|OCIHandleFree|))
|
73
|
+
=end
|
74
|
+
*/
|
75
|
+
VALUE oci8_handle_free(VALUE self)
|
76
|
+
{
|
77
|
+
oci8_handle_t *h;
|
78
|
+
|
79
|
+
Get_Handle(self, h);
|
80
|
+
oci8_handle_do_free(h);
|
81
|
+
return self;
|
82
|
+
}
|
83
|
+
|
84
|
+
void Init_oci8_handle(void)
|
85
|
+
{
|
86
|
+
rb_define_method(cOCIHandle, "free", oci8_handle_free, 0);
|
87
|
+
rb_define_method(cOCIHandle, "attrSet", oci8_attr_set, 2);
|
88
|
+
rb_define_method(cOCIHandle, "attrGet", oci8_attr_get, 1);
|
89
|
+
rb_define_singleton_method(cOCIHandle, "new", oci8_s_new, 0);
|
90
|
+
}
|
91
|
+
|
92
|
+
void oci8_handle_cleanup(oci8_handle_t *h)
|
93
|
+
{
|
94
|
+
oci8_handle_do_free(h);
|
95
|
+
xfree(h);
|
96
|
+
}
|
97
|
+
|
98
|
+
VALUE oci8_s_new(VALUE self)
|
99
|
+
{
|
100
|
+
rb_raise(rb_eNameError, "private method `new' called for %s:Class", rb_class2name(self));
|
101
|
+
}
|
102
|
+
|
103
|
+
|
104
|
+
static void oci8_handle_mark(oci8_handle_t *h)
|
105
|
+
{
|
106
|
+
oci8_bind_handle_t *bh;
|
107
|
+
int i;
|
108
|
+
|
109
|
+
switch (h->type) {
|
110
|
+
case OCI_HTYPE_SVCCTX:
|
111
|
+
for (i = 0;i < h->size;i++) {
|
112
|
+
if (h->children[i] != NULL) {
|
113
|
+
if (h->children[i]->type == OCI_HTYPE_SERVER || h->children[i]->type == OCI_HTYPE_SESSION) {
|
114
|
+
rb_gc_mark(h->children[i]->self);
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
break;
|
119
|
+
case OCI_HTYPE_STMT:
|
120
|
+
for (i = 0;i < h->size;i++) {
|
121
|
+
if (h->children[i] != NULL) {
|
122
|
+
if (h->children[i]->type == OCI_HTYPE_BIND || h->children[i]->type == OCI_HTYPE_DEFINE) {
|
123
|
+
rb_gc_mark(h->children[i]->self);
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
break;
|
128
|
+
case OCI_HTYPE_DEFINE:
|
129
|
+
case OCI_HTYPE_BIND:
|
130
|
+
bh = (oci8_bind_handle_t *)h;
|
131
|
+
if (bh->bind_type == BIND_HANDLE)
|
132
|
+
rb_gc_mark(bh->value.handle.v);
|
133
|
+
break;
|
134
|
+
}
|
135
|
+
if (h->parent != NULL) {
|
136
|
+
rb_gc_mark(h->parent->self);
|
137
|
+
}
|
138
|
+
}
|
139
|
+
|
140
|
+
oci8_handle_t *oci8_make_handle(ub4 type, dvoid *hp, OCIError *errhp, oci8_handle_t *parenth, sb4 value_sz)
|
141
|
+
{
|
142
|
+
VALUE obj;
|
143
|
+
oci8_handle_t *h;
|
144
|
+
oci8_bind_handle_t *bh;
|
145
|
+
|
146
|
+
switch (type) {
|
147
|
+
case OCI_HTYPE_ENV:
|
148
|
+
obj = Data_Make_Struct(cOCIEnv, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
149
|
+
break;
|
150
|
+
case OCI_HTYPE_SVCCTX:
|
151
|
+
obj = Data_Make_Struct(cOCISvcCtx, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
152
|
+
break;
|
153
|
+
case OCI_HTYPE_STMT:
|
154
|
+
obj = Data_Make_Struct(cOCIStmt, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
155
|
+
rb_ivar_set(obj, oci8_id_define_array, Qnil);
|
156
|
+
rb_ivar_set(obj, oci8_id_bind_hash, Qnil);
|
157
|
+
break;
|
158
|
+
case OCI_HTYPE_SERVER:
|
159
|
+
obj = Data_Make_Struct(cOCIServer, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
160
|
+
break;
|
161
|
+
case OCI_HTYPE_SESSION:
|
162
|
+
obj = Data_Make_Struct(cOCISession, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
163
|
+
break;
|
164
|
+
case OCI_HTYPE_DESCRIBE:
|
165
|
+
obj = Data_Make_Struct(cOCIDescribe, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
166
|
+
break;
|
167
|
+
case OCI_DTYPE_LOB:
|
168
|
+
obj = Data_Make_Struct(cOCILobLocator, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
169
|
+
#ifndef OCI8_USE_CALLBACK_LOB_READ
|
170
|
+
h->u.lob_locator.char_width = 1;
|
171
|
+
#endif
|
172
|
+
break;
|
173
|
+
case OCI_DTYPE_FILE:
|
174
|
+
obj = Data_Make_Struct(cOCIFileLocator, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
175
|
+
#ifndef OCI8_USE_CALLBACK_LOB_READ
|
176
|
+
h->u.lob_locator.char_width = 1;
|
177
|
+
#endif
|
178
|
+
break;
|
179
|
+
case OCI_DTYPE_ROWID:
|
180
|
+
obj = Data_Make_Struct(cOCIRowid, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
181
|
+
break;
|
182
|
+
case OCI_DTYPE_PARAM:
|
183
|
+
obj = Data_Make_Struct(cOCIParam, oci8_handle_t, oci8_handle_mark, oci8_handle_cleanup, h);
|
184
|
+
h->u.param.is_implicit = 0;
|
185
|
+
break;
|
186
|
+
case OCI_HTYPE_BIND:
|
187
|
+
bh = xmalloc(sizeof(oci8_bind_handle_t) - sizeof(bh->value) + value_sz);
|
188
|
+
memset(bh, 0, sizeof(oci8_bind_handle_t) - sizeof(bh->value) + value_sz);
|
189
|
+
obj = Data_Wrap_Struct(cOCIBind, oci8_handle_mark, oci8_handle_cleanup, bh);
|
190
|
+
bh->bind_type = 0;
|
191
|
+
bh->ind = -1;
|
192
|
+
bh->rlen = value_sz;
|
193
|
+
bh->value_sz = value_sz;
|
194
|
+
h = (oci8_handle_t *)bh;
|
195
|
+
break;
|
196
|
+
case OCI_HTYPE_DEFINE:
|
197
|
+
bh = xmalloc(sizeof(oci8_bind_handle_t) - sizeof(bh->value) + value_sz);
|
198
|
+
memset(bh, 0, sizeof(oci8_bind_handle_t) - sizeof(bh->value) + value_sz);
|
199
|
+
obj = Data_Wrap_Struct(cOCIDefine, oci8_handle_mark, oci8_handle_cleanup, bh);
|
200
|
+
bh->bind_type = 0;
|
201
|
+
bh->ind = -1;
|
202
|
+
bh->rlen = value_sz;
|
203
|
+
bh->value_sz = value_sz;
|
204
|
+
h = (oci8_handle_t *)bh;
|
205
|
+
break;
|
206
|
+
default:
|
207
|
+
rb_bug("unsupported type %d in oci8_make_handle()", type);
|
208
|
+
}
|
209
|
+
h->type = type;
|
210
|
+
h->hp = hp;
|
211
|
+
h->errhp = errhp;
|
212
|
+
h->self = obj;
|
213
|
+
h->parent = NULL;
|
214
|
+
h->size = 0;
|
215
|
+
h->children = NULL;
|
216
|
+
oci8_link(parenth, h);
|
217
|
+
return h;
|
218
|
+
}
|
219
|
+
|
220
|
+
#define CHILDREN_ARRAY_GROW_SIZE 16
|
221
|
+
|
222
|
+
void oci8_link(oci8_handle_t *parent, oci8_handle_t *child)
|
223
|
+
{
|
224
|
+
int i;
|
225
|
+
int new_size;
|
226
|
+
|
227
|
+
if (parent == NULL)
|
228
|
+
return;
|
229
|
+
oci8_unlink(child);
|
230
|
+
child->parent = parent;
|
231
|
+
|
232
|
+
for (i = 0;i < parent->size;i++) {
|
233
|
+
if (parent->children[i] == NULL) {
|
234
|
+
parent->children[i] = child;
|
235
|
+
return;
|
236
|
+
}
|
237
|
+
}
|
238
|
+
new_size = parent->size + CHILDREN_ARRAY_GROW_SIZE;
|
239
|
+
parent->children = xrealloc(parent->children, sizeof(oci8_handle_t *) * new_size);
|
240
|
+
parent->children[parent->size] = child;
|
241
|
+
for (i = parent->size + 1;i < new_size;i++) {
|
242
|
+
parent->children[i] = NULL;
|
243
|
+
}
|
244
|
+
parent->size = new_size;
|
245
|
+
return;
|
246
|
+
}
|
247
|
+
|
248
|
+
void oci8_unlink(oci8_handle_t *self)
|
249
|
+
{
|
250
|
+
oci8_handle_t *parent = self->parent;
|
251
|
+
int i;
|
252
|
+
|
253
|
+
if (self->parent == NULL)
|
254
|
+
return;
|
255
|
+
for (i = 0;i < parent->size;i++) {
|
256
|
+
if (parent->children[i] == self) {
|
257
|
+
parent->children[i] = NULL;
|
258
|
+
self->parent = NULL;
|
259
|
+
return;
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
data/ext/oci8/lob.c
ADDED
@@ -0,0 +1,386 @@
|
|
1
|
+
#include "oci8.h"
|
2
|
+
|
3
|
+
static VALUE sym_file_readonly;
|
4
|
+
|
5
|
+
#ifndef OCI8_USE_CALLBACK_LOB_READ
|
6
|
+
static VALUE oci8_lob_set_char_width(VALUE self, VALUE vsize)
|
7
|
+
{
|
8
|
+
oci8_handle_t *h;
|
9
|
+
int size;
|
10
|
+
|
11
|
+
Get_Handle(self, h); /* 0 */
|
12
|
+
size = NUM2INT(vsize); /* 1 */
|
13
|
+
|
14
|
+
if (size <= 0)
|
15
|
+
rb_raise(rb_eArgError, "size must be more than one.");
|
16
|
+
h->u.lob_locator.char_width = size;
|
17
|
+
return vsize;
|
18
|
+
}
|
19
|
+
#endif
|
20
|
+
|
21
|
+
static VALUE oci8_lob_is_initialized_p(VALUE self, VALUE venv)
|
22
|
+
{
|
23
|
+
oci8_handle_t *h;
|
24
|
+
oci8_handle_t *envh;
|
25
|
+
boolean is_initialized;
|
26
|
+
sword rv;
|
27
|
+
|
28
|
+
Get_Handle(self, h); /* 0 */
|
29
|
+
Check_Handle(venv, OCIEnv, envh); /* 1 */
|
30
|
+
|
31
|
+
rv = OCILobLocatorIsInit(envh->hp, h->errhp, h->hp, &is_initialized);
|
32
|
+
if (rv != OCI_SUCCESS)
|
33
|
+
oci8_raise(h->errhp, rv, NULL);
|
34
|
+
return is_initialized ? Qtrue : Qfalse;
|
35
|
+
}
|
36
|
+
|
37
|
+
|
38
|
+
/*
|
39
|
+
=begin
|
40
|
+
--- OCILobLocator#GetLength()
|
41
|
+
get the length of LOB.
|
42
|
+
counts by bytes for BLOB, by charactors for CLOB.
|
43
|
+
=end
|
44
|
+
*/
|
45
|
+
static VALUE oci8_lob_get_length(VALUE self, VALUE vsvc)
|
46
|
+
{
|
47
|
+
oci8_handle_t *h;
|
48
|
+
oci8_handle_t *svch;
|
49
|
+
ub4 len;
|
50
|
+
sword rv;
|
51
|
+
|
52
|
+
Get_Handle(self, h); /* 0 */
|
53
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
54
|
+
|
55
|
+
rv = OCILobGetLength(svch->hp, h->errhp, h->hp, &len);
|
56
|
+
if (rv != OCI_SUCCESS)
|
57
|
+
oci8_raise(h->errhp, rv, NULL);
|
58
|
+
return INT2FIX(len);
|
59
|
+
}
|
60
|
+
|
61
|
+
#ifdef HAVE_OCILOBGETCHUNKSIZE
|
62
|
+
static VALUE oci8_lob_get_chunk_size(VALUE self, VALUE vsvc)
|
63
|
+
{
|
64
|
+
oci8_handle_t *h;
|
65
|
+
oci8_handle_t *svch;
|
66
|
+
ub4 len;
|
67
|
+
sword rv;
|
68
|
+
|
69
|
+
Get_Handle(self, h); /* 0 */
|
70
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
71
|
+
|
72
|
+
rv = OCILobGetChunkSize(svch->hp, h->errhp, h->hp, &len);
|
73
|
+
if (rv != OCI_SUCCESS)
|
74
|
+
oci8_raise(h->errhp, rv, NULL);
|
75
|
+
return INT2FIX(len);
|
76
|
+
}
|
77
|
+
#endif
|
78
|
+
|
79
|
+
#ifdef OCI8_USE_CALLBACK_LOB_READ
|
80
|
+
static sb4 oci8_callback_lob_read(dvoid *ctxp, CONST dvoid *bufp, ub4 len, ub1 piece)
|
81
|
+
{
|
82
|
+
VALUE v = *((VALUE *)ctxp);
|
83
|
+
|
84
|
+
if (v == Qnil)
|
85
|
+
v = rb_str_new(bufp, len);
|
86
|
+
else
|
87
|
+
v = rb_str_cat(v, bufp, len);
|
88
|
+
|
89
|
+
*((VALUE *)ctxp) = v;
|
90
|
+
return OCI_CONTINUE;
|
91
|
+
}
|
92
|
+
#endif
|
93
|
+
|
94
|
+
static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
|
95
|
+
{
|
96
|
+
VALUE vsvc, voffset, vamt, vcsid, vcsfrm;
|
97
|
+
oci8_handle_t *h;
|
98
|
+
oci8_handle_t *svch;
|
99
|
+
ub4 offset;
|
100
|
+
ub2 csid;
|
101
|
+
ub1 csfrm;
|
102
|
+
ub4 amt;
|
103
|
+
sword rv;
|
104
|
+
char buf[4096];
|
105
|
+
#ifndef OCI8_USE_CALLBACK_LOB_READ
|
106
|
+
size_t buf_size_in_char;
|
107
|
+
#endif
|
108
|
+
VALUE v = Qnil;
|
109
|
+
|
110
|
+
rb_scan_args(argc, argv, "32", &vsvc, &voffset, &vamt, &vcsid, &vcsfrm);
|
111
|
+
Get_Handle(self, h); /* 0 */
|
112
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
113
|
+
offset = NUM2INT(voffset); /* 2 */
|
114
|
+
amt = NUM2INT(vamt); /* 3 */
|
115
|
+
csid = NIL_P(vcsid) ? 0 : NUM2INT(vcsid); /* 4 */
|
116
|
+
csfrm = NIL_P(vcsfrm) ? SQLCS_IMPLICIT : NUM2INT(vcsfrm); /* 5 */
|
117
|
+
|
118
|
+
#ifdef OCI8_USE_CALLBACK_LOB_READ
|
119
|
+
/* This raises ORA-24812, when the size of readed data is two or
|
120
|
+
* three times longer than the size of buf. I couldn't fix it. Thus
|
121
|
+
* I use polling way instead of callback method.
|
122
|
+
*/
|
123
|
+
rv = OCILobRead(svch->hp, h->errhp, h->hp, &amt, offset, buf, sizeof(buf), &v, oci8_callback_lob_read, csid, csfrm);
|
124
|
+
if (rv != OCI_SUCCESS)
|
125
|
+
oci8_raise(h->errhp, rv, NULL);
|
126
|
+
#else
|
127
|
+
/* Disadvantage of polling way in contrast with callback method is
|
128
|
+
* that it sets 'amt' the number of characters readed, when charset
|
129
|
+
* is fixed size. For single byte charset or variable size charset,
|
130
|
+
* it cause no problem because the unit of 'amt' is byte. But for
|
131
|
+
* fixed size multibyte charset, how can I know the size of a
|
132
|
+
* character from system? Therefore who want to use fixed size
|
133
|
+
* multibyte charset must set the size explicitly.
|
134
|
+
*
|
135
|
+
* Umm, if I could use callback method, I have no need to care about
|
136
|
+
* it.
|
137
|
+
*/
|
138
|
+
buf_size_in_char = sizeof(buf) / h->u.lob_locator.char_width;
|
139
|
+
do {
|
140
|
+
rv = OCILobRead(svch->hp, h->errhp, h->hp, &amt, offset, buf, sizeof(buf), NULL, NULL, csid, csfrm);
|
141
|
+
if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA)
|
142
|
+
oci8_raise(h->errhp, rv, NULL);
|
143
|
+
if (amt == 0)
|
144
|
+
break;
|
145
|
+
/* for fixed size charset, amt is the number of characters stored in buf. */
|
146
|
+
if (amt > buf_size_in_char)
|
147
|
+
rb_raise(eOCIException, "Too large buffer fetched or you set too large size of a character.");
|
148
|
+
amt *= h->u.lob_locator.char_width;
|
149
|
+
if (v == Qnil)
|
150
|
+
v = rb_str_new(buf, amt);
|
151
|
+
else
|
152
|
+
v = rb_str_cat(v, buf, amt);
|
153
|
+
} while (rv == OCI_NEED_DATA);
|
154
|
+
#endif
|
155
|
+
return v;
|
156
|
+
}
|
157
|
+
|
158
|
+
static VALUE oci8_lob_write(int argc, VALUE *argv, VALUE self)
|
159
|
+
{
|
160
|
+
VALUE vsvc, voffset, vbuf, vcsid, vcsfrm;
|
161
|
+
oci8_handle_t *h;
|
162
|
+
oci8_handle_t *svch;
|
163
|
+
oci8_string_t buf;
|
164
|
+
ub4 offset;
|
165
|
+
ub2 csid;
|
166
|
+
ub1 csfrm;
|
167
|
+
ub4 amt;
|
168
|
+
sword rv;
|
169
|
+
|
170
|
+
rb_scan_args(argc, argv, "32", &vsvc, &voffset, &vbuf, &vcsid, &vcsfrm);
|
171
|
+
Get_Handle(self, h); /* 0 */
|
172
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
173
|
+
offset = NUM2INT(voffset); /* 2 */
|
174
|
+
Get_String(vbuf, buf); /* 3 */
|
175
|
+
csid = NIL_P(vcsid) ? 0 : NUM2INT(vcsid); /* 4 */
|
176
|
+
csfrm = NIL_P(vcsfrm) ? SQLCS_IMPLICIT : NUM2INT(vcsfrm); /* 5 */
|
177
|
+
|
178
|
+
amt = buf.len;
|
179
|
+
rv = OCILobWrite(svch->hp, h->errhp, h->hp, &amt, offset, buf.ptr, buf.len, OCI_ONE_PIECE, NULL, NULL, csid, csfrm);
|
180
|
+
if (rv != OCI_SUCCESS)
|
181
|
+
oci8_raise(h->errhp, rv, NULL);
|
182
|
+
return INT2FIX(amt);
|
183
|
+
}
|
184
|
+
|
185
|
+
static VALUE oci8_lob_trim(VALUE self, VALUE vsvc, VALUE len)
|
186
|
+
{
|
187
|
+
oci8_handle_t *h;
|
188
|
+
oci8_handle_t *svch;
|
189
|
+
sword rv;
|
190
|
+
|
191
|
+
Get_Handle(self, h); /* 0 */
|
192
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
193
|
+
|
194
|
+
rv = OCILobTrim(svch->hp, h->errhp, h->hp, NUM2INT(len));
|
195
|
+
if (rv != OCI_SUCCESS)
|
196
|
+
oci8_raise(h->errhp, rv, NULL);
|
197
|
+
return self;
|
198
|
+
}
|
199
|
+
|
200
|
+
static VALUE oci8_lob_clone(VALUE self, VALUE vsvc)
|
201
|
+
{
|
202
|
+
oci8_handle_t *h;
|
203
|
+
oci8_handle_t *svch;
|
204
|
+
oci8_handle_t *envh;
|
205
|
+
oci8_handle_t *newh;
|
206
|
+
OCILobLocator *hp;
|
207
|
+
sword rv;
|
208
|
+
|
209
|
+
Get_Handle(self, h); /* 0 */
|
210
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
211
|
+
|
212
|
+
/* get environment handle */
|
213
|
+
for (envh = h; envh->type != OCI_HTYPE_ENV; envh = envh->parent);
|
214
|
+
rv = OCIDescriptorAlloc(envh->hp, (void *)&hp, h->type, 0, NULL);
|
215
|
+
if (rv != OCI_SUCCESS) {
|
216
|
+
oci8_env_raise(envh->hp, rv);
|
217
|
+
}
|
218
|
+
#ifdef HAVE_OCILOBLOCATORASSIGN
|
219
|
+
/* Oracle 8.1 or upper */
|
220
|
+
rv = OCILobLocatorAssign(svch->hp, h->errhp, h->hp, &hp);
|
221
|
+
#else
|
222
|
+
/* Oracle 8.0 */
|
223
|
+
rv = OCILobAssign(envh->hp, h->errhp, h->hp, &hp);
|
224
|
+
#endif
|
225
|
+
if (rv != OCI_SUCCESS) {
|
226
|
+
OCIDescriptorFree(hp, h->type);
|
227
|
+
oci8_raise(h->errhp, rv, NULL);
|
228
|
+
}
|
229
|
+
newh = oci8_make_handle(h->type, hp, h->errhp, h->parent, 0);
|
230
|
+
if (rv != OCI_SUCCESS)
|
231
|
+
oci8_raise(h->errhp, rv, NULL);
|
232
|
+
return newh->self;
|
233
|
+
}
|
234
|
+
|
235
|
+
#ifdef HAVE_OCILOBOPEN
|
236
|
+
static VALUE oci8_lob_open(int argc, VALUE *argv, VALUE self)
|
237
|
+
{
|
238
|
+
VALUE vsvc;
|
239
|
+
VALUE vmode = Qnil;
|
240
|
+
oci8_handle_t *h;
|
241
|
+
oci8_handle_t *svch;
|
242
|
+
ub1 mode;
|
243
|
+
sword rv;
|
244
|
+
|
245
|
+
rb_scan_args(argc, argv, "11", &vsvc, &vmode);
|
246
|
+
Get_Handle(self, h); /* 0 */
|
247
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
248
|
+
if (vmode == Qnil)
|
249
|
+
mode = OCI_DEFAULT;
|
250
|
+
else if (vmode == sym_file_readonly)
|
251
|
+
mode = OCI_FILE_READONLY;
|
252
|
+
else
|
253
|
+
rb_raise(rb_eArgError, "expect nil or :file_readonly");
|
254
|
+
rv = OCILobOpen(svch->hp, h->errhp, h->hp, mode);
|
255
|
+
if (rv != OCI_SUCCESS)
|
256
|
+
oci8_raise(h->errhp, rv, NULL);
|
257
|
+
return self;
|
258
|
+
}
|
259
|
+
#endif
|
260
|
+
|
261
|
+
#ifdef HAVE_OCILOBCLOSE
|
262
|
+
static VALUE oci8_lob_close(VALUE self, VALUE vsvc)
|
263
|
+
{
|
264
|
+
oci8_handle_t *h;
|
265
|
+
oci8_handle_t *svch;
|
266
|
+
sword rv;
|
267
|
+
|
268
|
+
Get_Handle(self, h); /* 0 */
|
269
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
270
|
+
|
271
|
+
rv = OCILobClose(svch->hp, h->errhp, h->hp);
|
272
|
+
if (rv != OCI_SUCCESS)
|
273
|
+
oci8_raise(h->errhp, rv, NULL);
|
274
|
+
return self;
|
275
|
+
}
|
276
|
+
#endif
|
277
|
+
|
278
|
+
static VALUE oci8_lobfile_name(VALUE self, VALUE venv)
|
279
|
+
{
|
280
|
+
oci8_handle_t *h;
|
281
|
+
oci8_handle_t *envh;
|
282
|
+
char dir_alias[31];
|
283
|
+
ub2 d_length = sizeof(dir_alias);
|
284
|
+
char filename[256];
|
285
|
+
ub2 f_length = sizeof(filename);
|
286
|
+
sword rv;
|
287
|
+
|
288
|
+
Get_Handle(self, h); /* 0 */
|
289
|
+
Check_Handle(venv, OCIEnv, envh); /* 1 */
|
290
|
+
|
291
|
+
rv = OCILobFileGetName(envh->hp, h->errhp, h->hp, (OraText*)dir_alias, &d_length, (OraText*)filename, &f_length);
|
292
|
+
if (rv != OCI_SUCCESS)
|
293
|
+
oci8_raise(h->errhp, rv, NULL);
|
294
|
+
return rb_ary_new3(2, rb_str_new(dir_alias, d_length), rb_str_new(filename, f_length));
|
295
|
+
}
|
296
|
+
|
297
|
+
static VALUE oci8_lobfile_set_name(VALUE self, VALUE venv, VALUE vdir, VALUE vfile)
|
298
|
+
{
|
299
|
+
oci8_handle_t *h;
|
300
|
+
oci8_handle_t *envh;
|
301
|
+
sword rv;
|
302
|
+
|
303
|
+
Get_Handle(self, h); /* 0 */
|
304
|
+
Check_Handle(venv, OCIEnv, envh); /* 1 */
|
305
|
+
StringValue(vdir); /* 2 */
|
306
|
+
StringValue(vfile); /* 3 */
|
307
|
+
|
308
|
+
rv = OCILobFileSetName(envh->hp, h->errhp, (OCILobLocator **)&h->hp,
|
309
|
+
RSTRING_ORATEXT(vdir), RSTRING_LEN(vdir),
|
310
|
+
RSTRING_ORATEXT(vfile), RSTRING_LEN(vfile));
|
311
|
+
if (rv != OCI_SUCCESS)
|
312
|
+
oci8_raise(h->errhp, rv, NULL);
|
313
|
+
return self;
|
314
|
+
}
|
315
|
+
|
316
|
+
static VALUE oci8_lobfile_exist_p(VALUE self, VALUE vsvc)
|
317
|
+
{
|
318
|
+
oci8_handle_t *h;
|
319
|
+
oci8_handle_t *svch;
|
320
|
+
boolean flag;
|
321
|
+
sword rv;
|
322
|
+
|
323
|
+
Get_Handle(self, h); /* 0 */
|
324
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
325
|
+
|
326
|
+
rv = OCILobFileExists(svch->hp, h->errhp, h->hp, &flag);
|
327
|
+
if (rv != OCI_SUCCESS)
|
328
|
+
oci8_raise(h->errhp, rv, NULL);
|
329
|
+
return flag ? Qtrue : Qfalse;
|
330
|
+
}
|
331
|
+
|
332
|
+
static VALUE oci8_lob_create_temporary(VALUE self, VALUE vsvc, VALUE vcsid, VALUE vcsfrm, VALUE vlobtype, VALUE vcache, VALUE vduration)
|
333
|
+
{
|
334
|
+
#ifdef HAVE_OCILOBCREATETEMPORARY
|
335
|
+
oci8_handle_t *h;
|
336
|
+
oci8_handle_t *svch;
|
337
|
+
ub2 csid;
|
338
|
+
ub1 csfrm;
|
339
|
+
ub1 lobtype;
|
340
|
+
boolean cache;
|
341
|
+
OCIDuration duration;
|
342
|
+
sword rv;
|
343
|
+
|
344
|
+
Get_Handle(self, h); /* 0 */
|
345
|
+
Check_Handle(vsvc, OCISvcCtx, svch); /* 1 */
|
346
|
+
csid = NIL_P(vcsid) ? 0 : NUM2INT(vcsid); /* 2 */
|
347
|
+
csfrm = NIL_P(vcsfrm) ? SQLCS_IMPLICIT : NUM2INT(vcsfrm); /* 3 */
|
348
|
+
lobtype = NUM2INT(vlobtype); /* 4 */
|
349
|
+
cache = RTEST(vcache) ? TRUE : FALSE; /* 5 */
|
350
|
+
duration = NIL_P(vduration) ? OCI_DURATION_SESSION : NUM2INT(vduration); /* 6 */
|
351
|
+
|
352
|
+
rv = OCILobCreateTemporary(svch->hp, h->errhp, h->hp, csid, csfrm, lobtype, cache, duration);
|
353
|
+
if (rv != OCI_SUCCESS)
|
354
|
+
oci8_raise(h->errhp, rv, NULL);
|
355
|
+
return self;
|
356
|
+
#else
|
357
|
+
rb_notimplement();
|
358
|
+
#endif
|
359
|
+
}
|
360
|
+
|
361
|
+
void Init_oci8_lob(void)
|
362
|
+
{
|
363
|
+
sym_file_readonly = ID2SYM(rb_intern("file_readonly"));
|
364
|
+
#ifndef OCI8_USE_CALLBACK_LOB_READ
|
365
|
+
rb_define_method(cOCILobLocator, "char_width=", oci8_lob_set_char_width, 1);
|
366
|
+
#endif
|
367
|
+
rb_define_method(cOCILobLocator, "is_initialized?", oci8_lob_is_initialized_p, 1);
|
368
|
+
rb_define_method(cOCILobLocator, "getLength", oci8_lob_get_length, 1);
|
369
|
+
#ifdef HAVE_OCILOBGETCHUNKSIZE
|
370
|
+
rb_define_method(cOCILobLocator, "getChunkSize", oci8_lob_get_chunk_size, 1);
|
371
|
+
#endif
|
372
|
+
rb_define_method(cOCILobLocator, "read", oci8_lob_read, -1);
|
373
|
+
rb_define_method(cOCILobLocator, "write", oci8_lob_write, -1);
|
374
|
+
rb_define_method(cOCILobLocator, "trim", oci8_lob_trim, 2);
|
375
|
+
rb_define_method(cOCILobLocator, "clone", oci8_lob_clone, 1);
|
376
|
+
#ifdef HAVE_OCILOBOPEN
|
377
|
+
rb_define_method(cOCILobLocator, "open", oci8_lob_open, -1);
|
378
|
+
#endif
|
379
|
+
#ifdef HAVE_OCILOBCLOSE
|
380
|
+
rb_define_method(cOCILobLocator, "close", oci8_lob_close, 1);
|
381
|
+
#endif
|
382
|
+
rb_define_method(cOCIFileLocator, "name", oci8_lobfile_name, 1);
|
383
|
+
rb_define_method(cOCIFileLocator, "set_name", oci8_lobfile_set_name, 3);
|
384
|
+
rb_define_method(cOCIFileLocator, "exists?", oci8_lobfile_exist_p, 1);
|
385
|
+
rb_define_method(cOCILobLocator, "create_temporary", oci8_lob_create_temporary, 6);
|
386
|
+
}
|