ruby-oci8-master 2.0.7

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 (84) hide show
  1. data/ChangeLog +2321 -0
  2. data/Makefile +88 -0
  3. data/NEWS +303 -0
  4. data/README +76 -0
  5. data/VERSION +1 -0
  6. data/dist-files +83 -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/.document +18 -0
  13. data/ext/oci8/MANIFEST +18 -0
  14. data/ext/oci8/apiwrap.c.tmpl +182 -0
  15. data/ext/oci8/apiwrap.h.tmpl +61 -0
  16. data/ext/oci8/apiwrap.rb +91 -0
  17. data/ext/oci8/apiwrap.yml +1455 -0
  18. data/ext/oci8/attr.c +105 -0
  19. data/ext/oci8/bind.c +366 -0
  20. data/ext/oci8/connection_pool.c +199 -0
  21. data/ext/oci8/encoding.c +289 -0
  22. data/ext/oci8/env.c +178 -0
  23. data/ext/oci8/error.c +378 -0
  24. data/ext/oci8/extconf.rb +179 -0
  25. data/ext/oci8/lob.c +805 -0
  26. data/ext/oci8/metadata.c +232 -0
  27. data/ext/oci8/object.c +727 -0
  28. data/ext/oci8/oci8.c +1156 -0
  29. data/ext/oci8/oci8.h +574 -0
  30. data/ext/oci8/oci8lib.c +527 -0
  31. data/ext/oci8/ocidatetime.c +484 -0
  32. data/ext/oci8/ocihandle.c +751 -0
  33. data/ext/oci8/ocinumber.c +1612 -0
  34. data/ext/oci8/oraconf.rb +1119 -0
  35. data/ext/oci8/oradate.c +611 -0
  36. data/ext/oci8/oranumber_util.c +352 -0
  37. data/ext/oci8/oranumber_util.h +24 -0
  38. data/ext/oci8/post-config.rb +5 -0
  39. data/ext/oci8/stmt.c +673 -0
  40. data/ext/oci8/thread_util.c +85 -0
  41. data/ext/oci8/thread_util.h +30 -0
  42. data/ext/oci8/win32.c +137 -0
  43. data/lib/.document +1 -0
  44. data/lib/dbd/OCI8.rb +591 -0
  45. data/lib/oci8.rb.in +94 -0
  46. data/lib/oci8/.document +8 -0
  47. data/lib/oci8/bindtype.rb +349 -0
  48. data/lib/oci8/compat.rb +113 -0
  49. data/lib/oci8/connection_pool.rb +99 -0
  50. data/lib/oci8/datetime.rb +611 -0
  51. data/lib/oci8/encoding-init.rb +74 -0
  52. data/lib/oci8/encoding.yml +537 -0
  53. data/lib/oci8/metadata.rb +2132 -0
  54. data/lib/oci8/object.rb +581 -0
  55. data/lib/oci8/oci8.rb +721 -0
  56. data/lib/oci8/ocihandle.rb +425 -0
  57. data/lib/oci8/oracle_version.rb +144 -0
  58. data/lib/oci8/properties.rb +73 -0
  59. data/metaconfig +142 -0
  60. data/pre-distclean.rb +7 -0
  61. data/ruby-oci8.gemspec +63 -0
  62. data/setup.rb +1331 -0
  63. data/test/README +4 -0
  64. data/test/config.rb +122 -0
  65. data/test/test_all.rb +51 -0
  66. data/test/test_appinfo.rb +63 -0
  67. data/test/test_array_dml.rb +333 -0
  68. data/test/test_bind_raw.rb +46 -0
  69. data/test/test_bind_time.rb +178 -0
  70. data/test/test_break.rb +96 -0
  71. data/test/test_clob.rb +82 -0
  72. data/test/test_connstr.rb +81 -0
  73. data/test/test_datetime.rb +582 -0
  74. data/test/test_dbi.rb +366 -0
  75. data/test/test_dbi_clob.rb +53 -0
  76. data/test/test_encoding.rb +100 -0
  77. data/test/test_error.rb +88 -0
  78. data/test/test_metadata.rb +1399 -0
  79. data/test/test_oci8.rb +434 -0
  80. data/test/test_oracle_version.rb +70 -0
  81. data/test/test_oradate.rb +256 -0
  82. data/test/test_oranumber.rb +746 -0
  83. data/test/test_rowid.rb +33 -0
  84. metadata +137 -0
@@ -0,0 +1,179 @@
1
+ begin
2
+ require 'mkmf'
3
+ rescue LoadError
4
+ if /linux/ =~ RUBY_PLATFORM
5
+ raise <<EOS
6
+ You need to install a ruby development package ruby-devel, ruby-dev or so.
7
+ EOS
8
+ end
9
+ raise
10
+ end
11
+
12
+ require File.dirname(__FILE__) + '/oraconf'
13
+ require File.dirname(__FILE__) + '/apiwrap'
14
+ require File.dirname(__FILE__) + '/../../lib/oci8/oracle_version.rb'
15
+
16
+ RUBY_OCI8_VERSION = File.read("#{File.dirname(__FILE__)}/../../VERSION").chomp
17
+
18
+ oraconf = OraConf.get()
19
+
20
+ def replace_keyword(source, target, replace)
21
+ puts "creating #{target} from #{source}"
22
+ open(source, "rb") { |f|
23
+ buf = f.read
24
+ replace.each do |key, value|
25
+ buf.gsub!('@@' + key + '@@', value)
26
+ end
27
+ open(target, "wb") {|fw|
28
+ fw.write buf
29
+ }
30
+ }
31
+ end
32
+
33
+ $CFLAGS += oraconf.cflags
34
+ saved_libs = $libs
35
+ $libs += oraconf.libs
36
+
37
+ oci_actual_client_version = 0x08000000
38
+ funcs = {}
39
+ YAML.load(open(File.dirname(__FILE__) + '/apiwrap.yml')).each do |key, val|
40
+ key = key[0..-4] if key[-3..-1] == '_nb'
41
+ ver = val[:version]
42
+ ver_major = (ver / 100)
43
+ ver_minor = (ver / 10) % 10
44
+ ver_update = ver % 10
45
+ ver = ((ver_major << 24) | (ver_minor << 20) | (ver_update << 12))
46
+ funcs[ver] ||= []
47
+ funcs[ver] << key
48
+ end
49
+ funcs.keys.sort.each do |version|
50
+ next if version == 0x08000000
51
+ verstr = format('%d.%d.%d', ((version >> 24) & 0xFF), ((version >> 20) & 0xF), ((version >> 12) & 0xFF))
52
+ puts "checking for Oracle #{verstr} API - start"
53
+ result = catch :result do
54
+ funcs[version].sort.each do |func|
55
+ unless have_func(func)
56
+ throw :result, "fail"
57
+ end
58
+ end
59
+ oci_actual_client_version = version
60
+ "pass"
61
+ end
62
+ puts "checking for Oracle #{verstr} API - #{result}"
63
+ break if result == 'fail'
64
+ end
65
+
66
+ have_type('oratext', 'ociap.h')
67
+ have_type('OCIDateTime*', 'ociap.h')
68
+ have_type('OCIInterval*', 'ociap.h')
69
+ have_type('OCICallbackLobRead2', 'ociap.h')
70
+ have_type('OCICallbackLobWrite2', 'ociap.h')
71
+ have_type('OCIAdmin*', 'ociap.h')
72
+ have_type('OCIAuthInfo*', 'ociap.h')
73
+ have_type('OCIMsg*', 'ociap.h')
74
+ have_type('OCICPool*', 'ociap.h')
75
+
76
+ if with_config('oracle-version')
77
+ oci_client_version = OCI8::OracleVersion.new(with_config('oracle-version')).to_i
78
+ else
79
+ oci_client_version = oci_actual_client_version
80
+ end
81
+ $defs << "-DORACLE_CLIENT_VERSION=#{format('0x%08x', oci_client_version)}"
82
+
83
+ if with_config('runtime-check')
84
+ $defs << "-DRUNTIME_API_CHECK=1"
85
+ $libs = saved_libs
86
+ end
87
+
88
+ $objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", "ocihandle.o",
89
+ "connection_pool.o",
90
+ "stmt.o", "bind.o", "metadata.o", "attr.o",
91
+ "lob.o", "oradate.o",
92
+ "ocinumber.o", "ocidatetime.o", "object.o", "apiwrap.o",
93
+ "encoding.o", "oranumber_util.o", "thread_util.o"]
94
+
95
+ if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
96
+ $defs << "-DUSE_WIN32_C"
97
+ $objs << "win32.o"
98
+ end
99
+
100
+ # Checking gcc or not
101
+ if oraconf.cc_is_gcc
102
+ $CFLAGS += " -Wall"
103
+ end
104
+
105
+ have_func("localtime_r")
106
+
107
+ # ruby 1.8 headers
108
+ have_header("intern.h")
109
+ have_header("util.h")
110
+ # ruby 1.9 headers
111
+ have_header("ruby/util.h")
112
+ have_type('rb_encoding', ['ruby/ruby.h', 'ruby/encoding.h'])
113
+
114
+ # $! in C API
115
+ have_var("ruby_errinfo", "ruby.h") # ruby 1.8
116
+ have_func("rb_errinfo", "ruby.h") # ruby 1.9
117
+
118
+ have_type("rb_blocking_function_t*", "ruby.h")
119
+ have_func("rb_set_end_proc", "ruby.h")
120
+ have_func("rb_class_superclass", "ruby.h")
121
+ have_func("rb_thread_blocking_region", "ruby.h")
122
+
123
+ # replace files
124
+ replace = {
125
+ 'OCI8_CLIENT_VERSION' => oraconf.version,
126
+ 'OCI8_MODULE_VERSION' => RUBY_OCI8_VERSION
127
+ }
128
+
129
+ # make ruby script before running create_makefile.
130
+ replace_keyword(File.dirname(__FILE__) + '/../../lib/oci8.rb.in', '../../lib/oci8.rb', replace)
131
+
132
+ so_basename = 'oci8lib_'
133
+ if defined? RUBY_ENGINE and RUBY_ENGINE != 'ruby'
134
+ so_basename += RUBY_ENGINE
135
+ end
136
+
137
+ # Config::CONFIG["ruby_version"] indicates the ruby API version.
138
+ # 1.8 - ruby 1.8.x
139
+ # 1.9.1 - ruby 1.9.1 and 1.9.2
140
+ # 1.9.x - ruby 1.9.x future version which will break the API compatibility
141
+ so_basename += Config::CONFIG["ruby_version"].gsub(/\W/, '')
142
+
143
+ $defs << "-DInit_oci8lib=Init_#{so_basename}"
144
+ $defs << "-Doci8lib=#{so_basename}"
145
+ $defs << "-DOCI8LIB_VERSION=\\\"#{RUBY_OCI8_VERSION}\\\""
146
+ if defined? RUBY_ENGINE and RUBY_ENGINE == 'rbx'
147
+ $defs << "-DCHAR_IS_NOT_A_SHORTCUT_TO_ID"
148
+ end
149
+
150
+ create_header()
151
+
152
+ # make dependency file
153
+ open("depend", "w") do |f|
154
+ extconf_opt = ''
155
+ ['oracle-version', 'runtime-check'].each do |arg|
156
+ opt = with_config(arg)
157
+ case opt
158
+ when String
159
+ extconf_opt += " --with-#{arg}=#{opt}"
160
+ when true
161
+ extconf_opt += " --with-#{arg}=yes"
162
+ when false
163
+ extconf_opt += " --with-#{arg}=no"
164
+ end
165
+ end
166
+ f.puts("Makefile: $(srcdir)/extconf.rb $(srcdir)/oraconf.rb")
167
+ f.puts("\t$(RUBY) $(srcdir)/extconf.rb#{extconf_opt}")
168
+ $objs.each do |obj|
169
+ f.puts("#{obj}: $(srcdir)/#{obj.sub(/\.o$/, ".c")} $(srcdir)/oci8.h apiwrap.h Makefile")
170
+ end
171
+ f.puts("apiwrap.c apiwrap.h: $(srcdir)/apiwrap.c.tmpl $(srcdir)/apiwrap.h.tmpl $(srcdir)/apiwrap.yml $(srcdir)/apiwrap.rb")
172
+ f.puts("\t$(RUBY) $(srcdir)/apiwrap.rb")
173
+ end
174
+
175
+ create_apiwrap()
176
+
177
+ create_makefile(so_basename)
178
+
179
+ exit 0
@@ -0,0 +1,805 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ #include "oci8.h"
3
+
4
+ static ID id_plus;
5
+ static ID id_dir_alias;
6
+ static ID id_filename;
7
+ static VALUE cOCI8LOB;
8
+ static VALUE cOCI8CLOB;
9
+ static VALUE cOCI8NCLOB;
10
+ static VALUE cOCI8BLOB;
11
+ static VALUE cOCI8BFILE;
12
+ static VALUE seek_set;
13
+ static VALUE seek_cur;
14
+ static VALUE seek_end;
15
+
16
+ enum state {
17
+ S_NO_OPEN_CLOSE,
18
+ S_OPEN,
19
+ S_CLOSE,
20
+ S_BFILE_CLOSE,
21
+ S_BFILE_OPEN,
22
+ };
23
+ typedef struct {
24
+ oci8_base_t base;
25
+ VALUE svc;
26
+ OCISvcCtx *svchp;
27
+ ub4 pos;
28
+ int char_width;
29
+ ub1 csfrm;
30
+ ub1 lobtype;
31
+ enum state state;
32
+ } oci8_lob_t;
33
+
34
+ static VALUE oci8_lob_write(VALUE self, VALUE data);
35
+
36
+ static VALUE oci8_make_lob(VALUE klass, oci8_svcctx_t *svcctx, OCILobLocator *s)
37
+ {
38
+ oci8_lob_t *lob;
39
+ VALUE lob_obj;
40
+
41
+ lob_obj = rb_funcall(klass, oci8_id_new, 1, svcctx->base.self);
42
+ lob = DATA_PTR(lob_obj);
43
+ /* If 's' is a temporary lob, use OCILobLocatorAssign instead. */
44
+ chker2(OCILobAssign(oci8_envhp, oci8_errhp, s, &lob->base.hp.lob),
45
+ &svcctx->base);
46
+ return lob_obj;
47
+ }
48
+
49
+ VALUE oci8_make_clob(oci8_svcctx_t *svcctx, OCILobLocator *s)
50
+ {
51
+ return oci8_make_lob(cOCI8CLOB, svcctx, s);
52
+ }
53
+
54
+ VALUE oci8_make_nclob(oci8_svcctx_t *svcctx, OCILobLocator *s)
55
+ {
56
+ return oci8_make_lob(cOCI8NCLOB, svcctx, s);
57
+ }
58
+
59
+ VALUE oci8_make_blob(oci8_svcctx_t *svcctx, OCILobLocator *s)
60
+ {
61
+ return oci8_make_lob(cOCI8BLOB, svcctx, s);
62
+ }
63
+
64
+ VALUE oci8_make_bfile(oci8_svcctx_t *svcctx, OCILobLocator *s)
65
+ {
66
+ return oci8_make_lob(cOCI8BFILE, svcctx, s);
67
+ }
68
+
69
+ static void oci8_assign_lob(VALUE klass, oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
70
+ {
71
+ oci8_base_t *base = oci8_get_handle(lob, klass);
72
+ chker2(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, base->hp.lob, dest), base);
73
+ }
74
+
75
+ void oci8_assign_clob(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
76
+ {
77
+ oci8_assign_lob(cOCI8CLOB, svcctx, lob, dest);
78
+ }
79
+
80
+ void oci8_assign_nclob(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
81
+ {
82
+ oci8_assign_lob(cOCI8NCLOB, svcctx, lob, dest);
83
+ }
84
+
85
+ void oci8_assign_blob(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
86
+ {
87
+ oci8_assign_lob(cOCI8BLOB, svcctx, lob, dest);
88
+ }
89
+
90
+ void oci8_assign_bfile(oci8_svcctx_t *svcctx, VALUE lob, OCILobLocator **dest)
91
+ {
92
+ oci8_assign_lob(cOCI8BFILE, svcctx, lob, dest);
93
+ }
94
+
95
+ static void oci8_lob_mark(oci8_base_t *base)
96
+ {
97
+ oci8_lob_t *lob = (oci8_lob_t *)base;
98
+ rb_gc_mark(lob->svc);
99
+ }
100
+
101
+ static void oci8_lob_free(oci8_base_t *base)
102
+ {
103
+ oci8_lob_t *lob = (oci8_lob_t *)base;
104
+ boolean is_temporary;
105
+
106
+ if (lob->svchp != NULL
107
+ && OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
108
+ && is_temporary) {
109
+
110
+ /* FIXME: This may stall the GC. */
111
+ OCILobFreeTemporary(lob->svchp, oci8_errhp, lob->base.hp.lob);
112
+ }
113
+ lob->svc = Qnil;
114
+ lob->svchp = NULL;
115
+ }
116
+
117
+ static oci8_base_vtable_t oci8_lob_vtable = {
118
+ oci8_lob_mark,
119
+ oci8_lob_free,
120
+ sizeof(oci8_lob_t),
121
+ };
122
+
123
+ static ub4 oci8_lob_get_length(oci8_lob_t *lob)
124
+ {
125
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
126
+ ub4 len;
127
+
128
+ chker2(OCILobGetLength_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len),
129
+ &svcctx->base);
130
+ return len;
131
+ }
132
+
133
+ static void lob_open(oci8_lob_t *lob)
134
+ {
135
+ if (lob->state == S_CLOSE) {
136
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
137
+
138
+ chker2(OCILobOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_DEFAULT),
139
+ &svcctx->base);
140
+ lob->state = S_OPEN;
141
+ }
142
+ }
143
+
144
+ static void lob_close(oci8_lob_t *lob)
145
+ {
146
+ if (lob->state == S_OPEN) {
147
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
148
+
149
+ chker2(OCILobClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
150
+ &svcctx->base);
151
+ lob->state = S_CLOSE;
152
+ }
153
+ }
154
+
155
+ static void bfile_close(oci8_lob_t *lob)
156
+ {
157
+ if (lob->state == S_BFILE_OPEN) {
158
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
159
+
160
+ chker2(OCILobFileClose_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob),
161
+ &svcctx->base);
162
+ lob->state = S_BFILE_CLOSE;
163
+ }
164
+ }
165
+
166
+ static VALUE oci8_lob_close(VALUE self)
167
+ {
168
+ oci8_lob_t *lob = DATA_PTR(self);
169
+ lob_close(lob);
170
+ oci8_base_free(DATA_PTR(self));
171
+ return self;
172
+ }
173
+
174
+ static VALUE oci8_lob_do_initialize(int argc, VALUE *argv, VALUE self, ub1 csfrm, ub1 lobtype)
175
+ {
176
+ oci8_lob_t *lob = DATA_PTR(self);
177
+ VALUE svc;
178
+ VALUE val;
179
+ sword rv;
180
+
181
+ rb_scan_args(argc, argv, "11", &svc, &val);
182
+ TO_SVCCTX(svc); /* check argument type */
183
+ rv = OCIDescriptorAlloc(oci8_envhp, &lob->base.hp.ptr, OCI_DTYPE_LOB, 0, NULL);
184
+ if (rv != OCI_SUCCESS)
185
+ oci8_env_raise(oci8_envhp, rv);
186
+ lob->base.type = OCI_DTYPE_LOB;
187
+ lob->svc = svc;
188
+ lob->svchp = NULL;
189
+ lob->pos = 0;
190
+ lob->char_width = 1;
191
+ lob->csfrm = csfrm;
192
+ lob->lobtype = lobtype;
193
+ lob->state = S_NO_OPEN_CLOSE;
194
+ oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
195
+ if (!NIL_P(val)) {
196
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
197
+ OCI8StringValue(val);
198
+ chker2(OCILobCreateTemporary_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, 0, csfrm, lobtype, TRUE, OCI_DURATION_SESSION),
199
+ &svcctx->base);
200
+ lob->svchp = oci8_get_oci_svcctx(svc);
201
+ oci8_lob_write(self, val);
202
+ }
203
+ return Qnil;
204
+ }
205
+
206
+ static VALUE oci8_clob_initialize(int argc, VALUE *argv, VALUE self)
207
+ {
208
+ oci8_lob_do_initialize(argc, argv, self, SQLCS_IMPLICIT, OCI_TEMP_CLOB);
209
+ return Qnil;
210
+ }
211
+
212
+ static VALUE oci8_nclob_initialize(int argc, VALUE *argv, VALUE self)
213
+ {
214
+ oci8_lob_do_initialize(argc, argv, self, SQLCS_NCHAR, OCI_TEMP_CLOB);
215
+ return Qnil;
216
+ }
217
+
218
+ static VALUE oci8_blob_initialize(int argc, VALUE *argv, VALUE self)
219
+ {
220
+ oci8_lob_do_initialize(argc, argv, self, SQLCS_IMPLICIT, OCI_TEMP_BLOB);
221
+ return Qnil;
222
+ }
223
+
224
+ static VALUE oci8_lob_set_char_width(VALUE self, VALUE vsize)
225
+ {
226
+ oci8_lob_t *lob = DATA_PTR(self);
227
+ int size;
228
+
229
+ size = NUM2INT(vsize); /* 1 */
230
+
231
+ if (size <= 0)
232
+ rb_raise(rb_eArgError, "size must be more than one.");
233
+ lob->char_width = size;
234
+ return vsize;
235
+ }
236
+
237
+ static VALUE oci8_lob_available_p(VALUE self)
238
+ {
239
+ oci8_lob_t *lob = DATA_PTR(self);
240
+ boolean is_initialized;
241
+
242
+ chker2(OCILobLocatorIsInit(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_initialized),
243
+ &lob->base);
244
+ return is_initialized ? Qtrue : Qfalse;
245
+ }
246
+
247
+ static VALUE oci8_lob_get_size(VALUE self)
248
+ {
249
+ return UB4_TO_NUM(oci8_lob_get_length(DATA_PTR(self)));
250
+ }
251
+
252
+ static VALUE oci8_lob_get_pos(VALUE self)
253
+ {
254
+ oci8_lob_t *lob = DATA_PTR(self);
255
+ return UB4_TO_NUM(lob->pos);
256
+ }
257
+
258
+ static VALUE oci8_lob_eof_p(VALUE self)
259
+ {
260
+ oci8_lob_t *lob = DATA_PTR(self);
261
+ if (oci8_lob_get_length(lob) < lob->pos)
262
+ return Qfalse;
263
+ else
264
+ return Qtrue;
265
+ }
266
+
267
+ static VALUE oci8_lob_seek(int argc, VALUE *argv, VALUE self)
268
+ {
269
+ oci8_lob_t *lob = DATA_PTR(self);
270
+ VALUE position, whence;
271
+
272
+ rb_scan_args(argc, argv, "11", &position, &whence);
273
+ if (argc == 2 && (whence != seek_set && whence != seek_cur && whence != seek_end)) {
274
+ if (FIXNUM_P(whence)) {
275
+ rb_raise(rb_eArgError, "expect IO::SEEK_SET, IO::SEEK_CUR or IO::SEEK_END but %d",
276
+ FIX2INT(whence));
277
+ } else {
278
+ rb_raise(rb_eArgError, "expect IO::SEEK_SET, IO::SEEK_CUR or IO::SEEK_END but %s",
279
+ rb_class2name(CLASS_OF(whence)));
280
+ }
281
+ }
282
+ if (whence == seek_cur) {
283
+ position = rb_funcall(UB4_TO_NUM(lob->pos), id_plus, 1, position);
284
+ } else if (whence == seek_end) {
285
+ position = rb_funcall(UB4_TO_NUM(oci8_lob_get_length(lob)), id_plus, 1, position);
286
+ }
287
+ lob->pos = NUM2UINT(position);
288
+ return self;
289
+ }
290
+
291
+ static VALUE oci8_lob_rewind(VALUE self)
292
+ {
293
+ oci8_lob_t *lob = DATA_PTR(self);
294
+ lob->pos = 0;
295
+ return self;
296
+ }
297
+
298
+ static VALUE oci8_lob_truncate(VALUE self, VALUE len)
299
+ {
300
+ oci8_lob_t *lob = DATA_PTR(self);
301
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
302
+
303
+ lob_open(lob);
304
+ chker2(OCILobTrim_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, NUM2UINT(len)),
305
+ &svcctx->base);
306
+ return self;
307
+ }
308
+
309
+ static VALUE oci8_lob_set_size(VALUE self, VALUE len)
310
+ {
311
+ oci8_lob_truncate(self, len);
312
+ return len;
313
+ }
314
+
315
+ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
316
+ {
317
+ oci8_lob_t *lob = DATA_PTR(self);
318
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
319
+ ub4 length;
320
+ ub4 nchar;
321
+ ub4 amt;
322
+ sword rv;
323
+ char buf[8192];
324
+ size_t buf_size_in_char;
325
+ VALUE size;
326
+ VALUE v = rb_ary_new();
327
+
328
+ rb_scan_args(argc, argv, "01", &size);
329
+ length = oci8_lob_get_length(lob);
330
+ if (length <= lob->pos) /* EOF */
331
+ return Qnil;
332
+ length -= lob->pos;
333
+ if (NIL_P(size)) {
334
+ nchar = length; /* read until EOF */
335
+ } else {
336
+ nchar = NUM2UINT(size);
337
+ if (nchar > length)
338
+ nchar = length;
339
+ }
340
+ amt = nchar;
341
+ buf_size_in_char = sizeof(buf) / lob->char_width;
342
+ do {
343
+ if (lob->state == S_BFILE_CLOSE) {
344
+ rv = OCILobFileOpen_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, OCI_FILE_READONLY);
345
+ if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22290) {
346
+ /* ORA-22290: operation would exceed the maximum number of opened files or LOBs */
347
+ /* close all opened BFILE implicitly. */
348
+ oci8_base_t *base;
349
+ for (base = &lob->base; base != &lob->base; base = base->next) {
350
+ if (base->type == OCI_DTYPE_LOB) {
351
+ oci8_lob_t *tmp = (oci8_lob_t *)base;
352
+ if (tmp->state == S_BFILE_OPEN) {
353
+ tmp->state = S_BFILE_CLOSE;
354
+ }
355
+ }
356
+ }
357
+ chker2(OCILobFileCloseAll_nb(svcctx, svcctx->base.hp.svc, oci8_errhp),
358
+ &svcctx->base);
359
+ continue;
360
+ }
361
+ chker2(rv, &svcctx->base);
362
+ lob->state = S_BFILE_OPEN;
363
+ }
364
+ /* initialize buf in zeros everytime to check a nul characters. */
365
+ memset(buf, 0, sizeof(buf));
366
+ rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf, sizeof(buf), NULL, NULL, 0, lob->csfrm);
367
+ if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22289) {
368
+ /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */
369
+ if (lob->state == S_BFILE_CLOSE)
370
+ continue;
371
+ }
372
+ if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA) {
373
+ chker2(rv, &svcctx->base);
374
+ }
375
+
376
+ /* Workaround when using Oracle 10.2.0.4 or 11.1.0.6 client and
377
+ * variable-length character set (e.g. AL32UTF8).
378
+ *
379
+ * When the above mentioned condition, amt may be shorter. So
380
+ * amt is increaded until a nul character to know the actually
381
+ * read size.
382
+ */
383
+ while (amt < sizeof(buf) && buf[amt] != '\0') {
384
+ amt++;
385
+ }
386
+
387
+ if (amt == 0)
388
+ break;
389
+ /* for fixed size charset, amt is the number of characters stored in buf. */
390
+ if (amt > buf_size_in_char)
391
+ rb_raise(eOCIException, "Too large buffer fetched or you set too large size of a character.");
392
+ amt *= lob->char_width;
393
+ rb_ary_push(v, rb_str_new(buf, amt));
394
+ } while (rv == OCI_NEED_DATA);
395
+ lob->pos += nchar;
396
+ if (nchar == length) {
397
+ lob_close(lob);
398
+ bfile_close(lob);
399
+ }
400
+ if (RARRAY_LEN(v) == 0) {
401
+ return Qnil;
402
+ }
403
+ v = rb_ary_join(v, Qnil);
404
+ OBJ_TAINT(v);
405
+ if (lob->lobtype == OCI_TEMP_CLOB) {
406
+ /* set encoding */
407
+ rb_enc_associate(v, oci8_encoding);
408
+ return rb_str_conv_enc(v, oci8_encoding, rb_default_internal_encoding());
409
+ } else {
410
+ /* ASCII-8BIT */
411
+ return v;
412
+ }
413
+ }
414
+
415
+ static VALUE oci8_lob_write(VALUE self, VALUE data)
416
+ {
417
+ oci8_lob_t *lob = DATA_PTR(self);
418
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
419
+ ub4 amt;
420
+
421
+ lob_open(lob);
422
+ if (TYPE(data) != T_STRING) {
423
+ data = rb_obj_as_string(data);
424
+ }
425
+ if (lob->lobtype == OCI_TEMP_CLOB) {
426
+ data = rb_str_export_to_enc(data, oci8_encoding);
427
+ }
428
+ RB_GC_GUARD(data);
429
+ amt = RSTRING_LEN(data);
430
+ chker2(OCILobWrite_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, RSTRING_PTR(data), amt, OCI_ONE_PIECE, NULL, NULL, 0, lob->csfrm),
431
+ &svcctx->base);
432
+ lob->pos += amt;
433
+ return UINT2NUM(amt);
434
+ }
435
+
436
+ static VALUE oci8_lob_get_sync(VALUE self)
437
+ {
438
+ oci8_lob_t *lob = DATA_PTR(self);
439
+ return (lob->state == S_NO_OPEN_CLOSE) ? Qtrue : Qfalse;
440
+ }
441
+
442
+ static VALUE oci8_lob_set_sync(VALUE self, VALUE b)
443
+ {
444
+ oci8_lob_t *lob = DATA_PTR(self);
445
+ if (RTEST(b)) {
446
+ lob_close(lob);
447
+ lob->state = S_NO_OPEN_CLOSE;
448
+ } else {
449
+ if (lob->state == S_NO_OPEN_CLOSE)
450
+ lob->state = S_CLOSE;
451
+ }
452
+ return b;
453
+ }
454
+
455
+ static VALUE oci8_lob_flush(VALUE self)
456
+ {
457
+ oci8_lob_t *lob = DATA_PTR(self);
458
+ lob_close(lob);
459
+ return self;
460
+ }
461
+
462
+ static VALUE oci8_lob_get_chunk_size(VALUE self)
463
+ {
464
+ oci8_lob_t *lob = DATA_PTR(self);
465
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
466
+ ub4 len;
467
+
468
+ chker2(OCILobGetChunkSize_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &len),
469
+ &svcctx->base);
470
+ return UINT2NUM(len);
471
+ }
472
+
473
+ static VALUE oci8_lob_clone(VALUE self)
474
+ {
475
+ oci8_lob_t *lob = DATA_PTR(self);
476
+ oci8_lob_t *newlob;
477
+ VALUE newobj;
478
+ boolean is_temporary;
479
+
480
+ newobj = rb_funcall(CLASS_OF(self), oci8_id_new, 1, lob->svc);
481
+ newlob = DATA_PTR(newobj);
482
+ if (OCILobIsTemporary(oci8_envhp, oci8_errhp, lob->base.hp.lob, &is_temporary) == OCI_SUCCESS
483
+ && is_temporary) {
484
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
485
+ chker2(OCILobLocatorAssign_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob),
486
+ &svcctx->base);
487
+ } else {
488
+ chker2(OCILobAssign(oci8_envhp, oci8_errhp, lob->base.hp.lob, &newlob->base.hp.lob), &lob->base);
489
+ }
490
+ return newobj;
491
+ }
492
+
493
+ static void oci8_bfile_get_name(VALUE self, VALUE *dir_alias_p, VALUE *filename_p)
494
+ {
495
+ int need_get = 0;
496
+ if (dir_alias_p != NULL) {
497
+ *dir_alias_p = rb_ivar_get(self, id_dir_alias);
498
+ if (NIL_P(*dir_alias_p))
499
+ need_get = 1;
500
+ }
501
+ if (filename_p != NULL) {
502
+ *filename_p = rb_ivar_get(self, id_filename);
503
+ if (NIL_P(*filename_p))
504
+ need_get = 1;
505
+ }
506
+ if (need_get) {
507
+ oci8_lob_t *lob = DATA_PTR(self);
508
+ char d_buf[31];
509
+ ub2 d_length = sizeof(d_buf);
510
+ char f_buf[256];
511
+ ub2 f_length = sizeof(f_buf);
512
+ VALUE dir_alias;
513
+ VALUE filename;
514
+
515
+ chker2(OCILobFileGetName(oci8_envhp, oci8_errhp, lob->base.hp.lob, TO_ORATEXT(d_buf), &d_length, TO_ORATEXT(f_buf), &f_length),
516
+ &lob->base);
517
+ dir_alias = rb_external_str_new_with_enc(d_buf, d_length, oci8_encoding);
518
+ filename = rb_external_str_new_with_enc(f_buf, f_length, oci8_encoding);
519
+ rb_ivar_set(self, id_dir_alias, dir_alias);
520
+ rb_ivar_set(self, id_filename, filename);
521
+ if (dir_alias_p != NULL) {
522
+ *dir_alias_p = dir_alias;
523
+ }
524
+ if (filename_p != NULL) {
525
+ *filename_p = filename;
526
+ }
527
+ }
528
+ }
529
+
530
+ static void oci8_bfile_set_name(VALUE self, VALUE dir_alias, VALUE filename)
531
+ {
532
+ oci8_lob_t *lob = DATA_PTR(self);
533
+
534
+ bfile_close(lob);
535
+ if (RSTRING_LEN(dir_alias) > UB2MAXVAL) {
536
+ rb_raise(rb_eRuntimeError, "dir_alias is too long.");
537
+ }
538
+ if (RSTRING_LEN(filename) > UB2MAXVAL) {
539
+ rb_raise(rb_eRuntimeError, "filename is too long.");
540
+ }
541
+ chker2(OCILobFileSetName(oci8_envhp, oci8_errhp, &lob->base.hp.lob,
542
+ RSTRING_ORATEXT(dir_alias), (ub2)RSTRING_LEN(dir_alias),
543
+ RSTRING_ORATEXT(filename), (ub2)RSTRING_LEN(filename)),
544
+ &lob->base);
545
+ }
546
+
547
+ static VALUE oci8_bfile_initialize(int argc, VALUE *argv, VALUE self)
548
+ {
549
+ oci8_lob_t *lob = DATA_PTR(self);
550
+ VALUE svc;
551
+ VALUE dir_alias;
552
+ VALUE filename;
553
+ int rv;
554
+
555
+ rb_scan_args(argc, argv, "12", &svc, &dir_alias, &filename);
556
+ TO_SVCCTX(svc); /* check argument type */
557
+ rv = OCIDescriptorAlloc(oci8_envhp, &lob->base.hp.ptr, OCI_DTYPE_LOB, 0, NULL);
558
+ if (rv != OCI_SUCCESS) {
559
+ oci8_env_raise(oci8_envhp, rv);
560
+ }
561
+ lob->base.type = OCI_DTYPE_LOB;
562
+ lob->svc = svc;
563
+ lob->pos = 0;
564
+ lob->char_width = 1;
565
+ lob->csfrm = SQLCS_IMPLICIT;
566
+ lob->lobtype = OCI_TEMP_BLOB;
567
+ lob->state = S_BFILE_CLOSE;
568
+ if (argc != 1) {
569
+ OCI8SafeStringValue(dir_alias);
570
+ OCI8SafeStringValue(filename);
571
+ oci8_bfile_set_name(self, dir_alias, filename);
572
+ }
573
+ oci8_link_to_parent((oci8_base_t*)lob, (oci8_base_t*)DATA_PTR(svc));
574
+ return Qnil;
575
+ }
576
+
577
+ static VALUE oci8_bfile_get_dir_alias(VALUE self)
578
+ {
579
+ VALUE dir_alias;
580
+
581
+ oci8_bfile_get_name(self, &dir_alias, NULL);
582
+ return dir_alias;
583
+ }
584
+
585
+ static VALUE oci8_bfile_get_filename(VALUE self)
586
+ {
587
+ VALUE filename;
588
+
589
+ oci8_bfile_get_name(self, NULL, &filename);
590
+ return filename;
591
+ }
592
+
593
+ static VALUE oci8_bfile_set_dir_alias(VALUE self, VALUE dir_alias)
594
+ {
595
+ VALUE filename;
596
+
597
+ OCI8SafeStringValue(dir_alias);
598
+ oci8_bfile_get_name(self, NULL, &filename);
599
+ oci8_bfile_set_name(self, dir_alias, filename);
600
+ rb_ivar_set(self, id_dir_alias, dir_alias);
601
+ return dir_alias;
602
+ }
603
+
604
+ static VALUE oci8_bfile_set_filename(VALUE self, VALUE filename)
605
+ {
606
+ VALUE dir_alias;
607
+
608
+ OCI8SafeStringValue(filename);
609
+ oci8_bfile_get_name(self, &dir_alias, NULL);
610
+ oci8_bfile_set_name(self, dir_alias, filename);
611
+ rb_ivar_set(self, id_filename, filename);
612
+ return filename;
613
+ }
614
+
615
+ static VALUE oci8_bfile_exists_p(VALUE self)
616
+ {
617
+ oci8_lob_t *lob = DATA_PTR(self);
618
+ oci8_svcctx_t *svcctx = oci8_get_svcctx(lob->svc);
619
+ boolean flag;
620
+
621
+ chker2(OCILobFileExists_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &flag),
622
+ &svcctx->base);
623
+ return flag ? Qtrue : Qfalse;
624
+ }
625
+
626
+ static VALUE oci8_bfile_error(VALUE self, VALUE dummy)
627
+ {
628
+ rb_raise(rb_eRuntimeError, "cannot modify a read-only BFILE object");
629
+ }
630
+
631
+ /*
632
+ * bind_clob/blob/bfile
633
+ */
634
+
635
+ typedef struct {
636
+ oci8_bind_vtable_t bind;
637
+ VALUE *klass;
638
+ } oci8_bind_lob_vtable_t;
639
+
640
+ static VALUE bind_lob_get(oci8_bind_t *obind, void *data, void *null_struct)
641
+ {
642
+ oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
643
+ return oci8_lob_clone(oho->obj);
644
+ }
645
+
646
+ static void bind_lob_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
647
+ {
648
+ oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
649
+ const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr;
650
+ oci8_base_t *h;
651
+ if (!rb_obj_is_kind_of(val, *vptr->klass))
652
+ rb_raise(rb_eArgError, "Invalid argument: %s (expect %s)", rb_class2name(CLASS_OF(val)), rb_class2name(*vptr->klass));
653
+ h = DATA_PTR(val);
654
+ oho->hp = h->hp.ptr;
655
+ oho->obj = val;
656
+ }
657
+
658
+ static void bind_lob_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
659
+ {
660
+ obind->value_sz = sizeof(void *);
661
+ obind->alloc_sz = sizeof(oci8_hp_obj_t);
662
+ }
663
+
664
+ static void bind_lob_init_elem(oci8_bind_t *obind, VALUE svc)
665
+ {
666
+ const oci8_bind_lob_vtable_t *vptr = (const oci8_bind_lob_vtable_t *)obind->base.vptr;
667
+ oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
668
+ oci8_base_t *h;
669
+ ub4 idx = 0;
670
+
671
+ do {
672
+ oho[idx].obj = rb_funcall(*vptr->klass, oci8_id_new, 1, svc);
673
+ h = DATA_PTR(oho[idx].obj);
674
+ oho[idx].hp = h->hp.ptr;
675
+ } while (++idx < obind->maxar_sz);
676
+ }
677
+
678
+ static void bind_lob_post_bind_hook_for_nclob(oci8_bind_t *obind)
679
+ {
680
+ ub1 csfrm = SQLCS_NCHAR;
681
+
682
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
683
+ &obind->base);
684
+ }
685
+
686
+ static const oci8_bind_lob_vtable_t bind_clob_vtable = {
687
+ {
688
+ {
689
+ oci8_bind_hp_obj_mark,
690
+ oci8_bind_free,
691
+ sizeof(oci8_bind_t)
692
+ },
693
+ bind_lob_get,
694
+ bind_lob_set,
695
+ bind_lob_init,
696
+ bind_lob_init_elem,
697
+ NULL,
698
+ SQLT_CLOB
699
+ },
700
+ &cOCI8CLOB
701
+ };
702
+
703
+ static const oci8_bind_lob_vtable_t bind_nclob_vtable = {
704
+ {
705
+ {
706
+ oci8_bind_hp_obj_mark,
707
+ oci8_bind_free,
708
+ sizeof(oci8_bind_t)
709
+ },
710
+ bind_lob_get,
711
+ bind_lob_set,
712
+ bind_lob_init,
713
+ bind_lob_init_elem,
714
+ NULL,
715
+ SQLT_CLOB,
716
+ bind_lob_post_bind_hook_for_nclob,
717
+ },
718
+ &cOCI8NCLOB
719
+ };
720
+
721
+ static const oci8_bind_lob_vtable_t bind_blob_vtable = {
722
+ {
723
+ {
724
+ oci8_bind_hp_obj_mark,
725
+ oci8_bind_free,
726
+ sizeof(oci8_bind_t)
727
+ },
728
+ bind_lob_get,
729
+ bind_lob_set,
730
+ bind_lob_init,
731
+ bind_lob_init_elem,
732
+ NULL,
733
+ SQLT_BLOB
734
+ },
735
+ &cOCI8BLOB
736
+ };
737
+
738
+ static const oci8_bind_lob_vtable_t bind_bfile_vtable = {
739
+ {
740
+ {
741
+ oci8_bind_hp_obj_mark,
742
+ oci8_bind_free,
743
+ sizeof(oci8_bind_t)
744
+ },
745
+ bind_lob_get,
746
+ bind_lob_set,
747
+ bind_lob_init,
748
+ bind_lob_init_elem,
749
+ NULL,
750
+ SQLT_BFILE
751
+ },
752
+ &cOCI8BFILE
753
+ };
754
+
755
+ void Init_oci8_lob(VALUE cOCI8)
756
+ {
757
+ id_plus = rb_intern("+");
758
+ id_dir_alias = rb_intern("@dir_alias");
759
+ id_filename = rb_intern("@filename");
760
+ seek_set = rb_eval_string("::IO::SEEK_SET");
761
+ seek_cur = rb_eval_string("::IO::SEEK_CUR");
762
+ seek_end = rb_eval_string("::IO::SEEK_END");
763
+
764
+ cOCI8LOB = oci8_define_class_under(cOCI8, "LOB", &oci8_lob_vtable);
765
+ cOCI8CLOB = rb_define_class_under(cOCI8, "CLOB", cOCI8LOB);
766
+ cOCI8NCLOB = rb_define_class_under(cOCI8, "NCLOB", cOCI8LOB);
767
+ cOCI8BLOB = rb_define_class_under(cOCI8, "BLOB", cOCI8LOB);
768
+ cOCI8BFILE = rb_define_class_under(cOCI8, "BFILE", cOCI8LOB);
769
+
770
+ rb_define_method(cOCI8CLOB, "initialize", oci8_clob_initialize, -1);
771
+ rb_define_method(cOCI8NCLOB, "initialize", oci8_nclob_initialize, -1);
772
+ rb_define_method(cOCI8BLOB, "initialize", oci8_blob_initialize, -1);
773
+ rb_define_private_method(cOCI8LOB, "__char_width=", oci8_lob_set_char_width, 1);
774
+ rb_define_method(cOCI8LOB, "available?", oci8_lob_available_p, 0);
775
+ rb_define_method(cOCI8LOB, "size", oci8_lob_get_size, 0);
776
+ rb_define_method(cOCI8LOB, "pos", oci8_lob_get_pos, 0);
777
+ rb_define_alias(cOCI8LOB, "tell", "pos");
778
+ rb_define_method(cOCI8LOB, "eof?", oci8_lob_eof_p, 0);
779
+ rb_define_method(cOCI8LOB, "seek", oci8_lob_seek, -1);
780
+ rb_define_method(cOCI8LOB, "rewind", oci8_lob_rewind, 0);
781
+ rb_define_method(cOCI8LOB, "truncate", oci8_lob_truncate, 1);
782
+ rb_define_method(cOCI8LOB, "size=", oci8_lob_set_size, 1);
783
+ rb_define_method(cOCI8LOB, "read", oci8_lob_read, -1);
784
+ rb_define_method(cOCI8LOB, "write", oci8_lob_write, 1);
785
+ rb_define_method(cOCI8LOB, "close", oci8_lob_close, 0);
786
+ rb_define_method(cOCI8LOB, "sync", oci8_lob_get_sync, 0);
787
+ rb_define_method(cOCI8LOB, "sync=", oci8_lob_set_sync, 1);
788
+ rb_define_method(cOCI8LOB, "flush", oci8_lob_flush, 0);
789
+ rb_define_method(cOCI8LOB, "chunk_size", oci8_lob_get_chunk_size, 0);
790
+
791
+ rb_define_method(cOCI8BFILE, "initialize", oci8_bfile_initialize, -1);
792
+ rb_define_method(cOCI8BFILE, "dir_alias", oci8_bfile_get_dir_alias, 0);
793
+ rb_define_method(cOCI8BFILE, "filename", oci8_bfile_get_filename, 0);
794
+ rb_define_method(cOCI8BFILE, "dir_alias=", oci8_bfile_set_dir_alias, 1);
795
+ rb_define_method(cOCI8BFILE, "filename=", oci8_bfile_set_filename, 1);
796
+ rb_define_method(cOCI8BFILE, "exists?", oci8_bfile_exists_p, 0);
797
+ rb_define_method(cOCI8BFILE, "truncate", oci8_bfile_error, 1);
798
+ rb_define_method(cOCI8BFILE, "size=", oci8_bfile_error, 1);
799
+ rb_define_method(cOCI8BFILE, "write", oci8_bfile_error, 1);
800
+
801
+ oci8_define_bind_class("CLOB", &bind_clob_vtable.bind);
802
+ oci8_define_bind_class("NCLOB", &bind_nclob_vtable.bind);
803
+ oci8_define_bind_class("BLOB", &bind_blob_vtable.bind);
804
+ oci8_define_bind_class("BFILE", &bind_bfile_vtable.bind);
805
+ }