ruby-oci8 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/ChangeLog +569 -0
  2. data/Makefile +51 -0
  3. data/NEWS +322 -0
  4. data/README +415 -0
  5. data/VERSION +1 -0
  6. data/dist-files +70 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/MANIFEST +22 -0
  13. data/ext/oci8/attr.c +415 -0
  14. data/ext/oci8/bind.c +194 -0
  15. data/ext/oci8/const.c +165 -0
  16. data/ext/oci8/define.c +53 -0
  17. data/ext/oci8/describe.c +81 -0
  18. data/ext/oci8/descriptor.c +39 -0
  19. data/ext/oci8/env.c +276 -0
  20. data/ext/oci8/error.c +234 -0
  21. data/ext/oci8/extconf.rb +118 -0
  22. data/ext/oci8/handle.c +262 -0
  23. data/ext/oci8/lob.c +386 -0
  24. data/ext/oci8/oci8.c +137 -0
  25. data/ext/oci8/oci8.h +345 -0
  26. data/ext/oci8/ocinumber.c +117 -0
  27. data/ext/oci8/oraconf.rb +1026 -0
  28. data/ext/oci8/oradate.c +426 -0
  29. data/ext/oci8/oranumber.c +445 -0
  30. data/ext/oci8/param.c +37 -0
  31. data/ext/oci8/post-config.rb +5 -0
  32. data/ext/oci8/server.c +182 -0
  33. data/ext/oci8/session.c +99 -0
  34. data/ext/oci8/stmt.c +624 -0
  35. data/ext/oci8/svcctx.c +229 -0
  36. data/lib/DBD/OCI8/OCI8.rb +549 -0
  37. data/lib/oci8.rb.in +1605 -0
  38. data/metaconfig +142 -0
  39. data/pre-distclean.rb +7 -0
  40. data/ruby-oci8.gemspec +54 -0
  41. data/ruby-oci8.spec +62 -0
  42. data/setup.rb +1331 -0
  43. data/support/README +4 -0
  44. data/support/runit/assert.rb +281 -0
  45. data/support/runit/cui/testrunner.rb +101 -0
  46. data/support/runit/error.rb +4 -0
  47. data/support/runit/method_mappable.rb +20 -0
  48. data/support/runit/robserver.rb +25 -0
  49. data/support/runit/setuppable.rb +15 -0
  50. data/support/runit/teardownable.rb +16 -0
  51. data/support/runit/testcase.rb +113 -0
  52. data/support/runit/testfailure.rb +25 -0
  53. data/support/runit/testresult.rb +121 -0
  54. data/support/runit/testsuite.rb +43 -0
  55. data/support/runit/version.rb +3 -0
  56. data/test/README +4 -0
  57. data/test/config.rb +129 -0
  58. data/test/test_all.rb +43 -0
  59. data/test/test_bind_raw.rb +53 -0
  60. data/test/test_bind_time.rb +191 -0
  61. data/test/test_break.rb +81 -0
  62. data/test/test_clob.rb +101 -0
  63. data/test/test_connstr.rb +80 -0
  64. data/test/test_dbi.rb +317 -0
  65. data/test/test_dbi_clob.rb +56 -0
  66. data/test/test_describe.rb +137 -0
  67. data/test/test_metadata.rb +243 -0
  68. data/test/test_oci8.rb +273 -0
  69. data/test/test_oradate.rb +263 -0
  70. data/test/test_oranumber.rb +149 -0
  71. metadata +118 -0
@@ -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
@@ -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
+ }
@@ -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
+ }