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