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.
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
+ }