ruby-oci8 1.0.7 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +1254 -390
- data/Makefile +10 -13
- data/README +56 -385
- data/VERSION +1 -1
- data/dist-files +26 -27
- data/ext/oci8/.document +1 -0
- data/ext/oci8/MANIFEST +0 -4
- data/ext/oci8/apiwrap.c.tmpl +172 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1243 -0
- data/ext/oci8/attr.c +124 -384
- data/ext/oci8/bind.c +472 -164
- data/ext/oci8/encoding.c +196 -0
- data/ext/oci8/env.c +84 -253
- data/ext/oci8/error.c +196 -127
- data/ext/oci8/extconf.rb +82 -59
- data/ext/oci8/lob.c +710 -370
- data/ext/oci8/metadata.c +359 -0
- data/ext/oci8/object.c +622 -0
- data/ext/oci8/oci8.c +577 -161
- data/ext/oci8/oci8.h +354 -258
- data/ext/oci8/oci8lib.c +493 -0
- data/ext/oci8/ocidatetime.c +473 -0
- data/ext/oci8/ocinumber.c +1123 -24
- data/ext/oci8/oraconf.rb +72 -106
- data/ext/oci8/oradate.c +511 -321
- data/ext/oci8/stmt.c +752 -572
- data/ext/oci8/win32.c +131 -0
- data/ext/oci8/xmldb.c +383 -0
- data/lib/.document +2 -0
- data/lib/dbd/OCI8.rb +2 -17
- data/lib/oci8.rb.in +41 -1622
- data/lib/oci8/.document +5 -0
- data/lib/oci8/compat.rb +108 -0
- data/lib/oci8/datetime.rb +489 -0
- data/lib/oci8/encoding-init.rb +40 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2077 -0
- data/lib/oci8/object.rb +548 -0
- data/lib/oci8/oci8.rb +773 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/metaconfig +3 -3
- data/ruby-oci8.gemspec +5 -5
- data/setup.rb +4 -4
- data/test/config.rb +64 -84
- data/test/test_all.rb +14 -21
- data/test/test_array_dml.rb +317 -0
- data/test/test_bind_raw.rb +18 -25
- data/test/test_bind_time.rb +78 -91
- data/test/test_break.rb +37 -35
- data/test/test_clob.rb +33 -89
- data/test/test_connstr.rb +5 -4
- data/test/test_datetime.rb +469 -0
- data/test/test_dbi.rb +99 -60
- data/test/test_dbi_clob.rb +3 -8
- data/test/test_metadata.rb +65 -51
- data/test/test_oci8.rb +151 -55
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +76 -83
- data/test/test_oranumber.rb +405 -71
- data/test/test_rowid.rb +6 -11
- metadata +31 -32
- data/NEWS +0 -420
- data/ext/oci8/const.c +0 -165
- data/ext/oci8/define.c +0 -53
- data/ext/oci8/describe.c +0 -81
- data/ext/oci8/descriptor.c +0 -39
- data/ext/oci8/handle.c +0 -273
- data/ext/oci8/oranumber.c +0 -445
- data/ext/oci8/param.c +0 -37
- data/ext/oci8/server.c +0 -182
- data/ext/oci8/session.c +0 -99
- data/ext/oci8/svcctx.c +0 -238
- data/ruby-oci8.spec +0 -62
- data/support/README +0 -4
- data/support/runit/assert.rb +0 -281
- data/support/runit/cui/testrunner.rb +0 -101
- data/support/runit/error.rb +0 -4
- data/support/runit/method_mappable.rb +0 -20
- data/support/runit/robserver.rb +0 -25
- data/support/runit/setuppable.rb +0 -15
- data/support/runit/teardownable.rb +0 -16
- data/support/runit/testcase.rb +0 -113
- data/support/runit/testfailure.rb +0 -25
- data/support/runit/testresult.rb +0 -121
- data/support/runit/testsuite.rb +0 -43
- data/support/runit/version.rb +0 -3
- data/test/test_describe.rb +0 -137
data/ext/oci8/metadata.c
ADDED
@@ -0,0 +1,359 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* metadata.c
|
4
|
+
*
|
5
|
+
* Copyright (C) 2006-2007 KUBO Takehiro <kubo@jiubao.org>
|
6
|
+
*
|
7
|
+
* implement private methods of classes in OCI8::Metadata module.
|
8
|
+
*
|
9
|
+
* public methods are implemented by oci8/metadata.rb.
|
10
|
+
*/
|
11
|
+
#include "oci8.h"
|
12
|
+
|
13
|
+
static VALUE mOCI8Metadata;
|
14
|
+
VALUE cOCI8MetadataBase;
|
15
|
+
static VALUE ptype_to_class;
|
16
|
+
static VALUE class_to_ptype;
|
17
|
+
|
18
|
+
typedef struct {
|
19
|
+
oci8_base_t base;
|
20
|
+
VALUE svc;
|
21
|
+
ub1 is_implicit;
|
22
|
+
} oci8_metadata_t;
|
23
|
+
|
24
|
+
static void oci8_metadata_mark(oci8_base_t *base)
|
25
|
+
{
|
26
|
+
oci8_metadata_t *md = (oci8_metadata_t *)base;
|
27
|
+
if (base->parent != NULL)
|
28
|
+
rb_gc_mark(base->parent->self);
|
29
|
+
rb_gc_mark(md->svc);
|
30
|
+
}
|
31
|
+
|
32
|
+
VALUE oci8_metadata_create(OCIParam *parmhp, VALUE svc, VALUE parent)
|
33
|
+
{
|
34
|
+
oci8_metadata_t *md;
|
35
|
+
oci8_base_t *p;
|
36
|
+
ub1 ptype;
|
37
|
+
ub4 size;
|
38
|
+
VALUE klass;
|
39
|
+
VALUE obj;
|
40
|
+
|
41
|
+
Check_Handle(parent, oci8_cOCIHandle, p);
|
42
|
+
|
43
|
+
oci_lc(OCIAttrGet(parmhp, OCI_DTYPE_PARAM, &ptype, &size, OCI_ATTR_PTYPE, oci8_errhp));
|
44
|
+
klass = rb_hash_aref(ptype_to_class, INT2FIX(ptype));
|
45
|
+
if (NIL_P(klass))
|
46
|
+
rb_raise(rb_eRuntimeError, "unknown parameter type %d", ptype);
|
47
|
+
obj = rb_obj_alloc(klass);
|
48
|
+
if (!RTEST(rb_obj_is_kind_of(obj, cOCI8MetadataBase))) {
|
49
|
+
rb_raise(rb_eRuntimeError, "invalid class in PTYPE_TO_CLASS");
|
50
|
+
}
|
51
|
+
md = DATA_PTR(obj);
|
52
|
+
md->base.type = OCI_DTYPE_PARAM;
|
53
|
+
md->base.hp.prm = parmhp;
|
54
|
+
md->svc = svc;
|
55
|
+
|
56
|
+
if (p->type == OCI_HTYPE_STMT) {
|
57
|
+
md->is_implicit = 1;
|
58
|
+
} else {
|
59
|
+
md->is_implicit = 0;
|
60
|
+
}
|
61
|
+
oci8_link_to_parent(&md->base, p);
|
62
|
+
return obj;
|
63
|
+
}
|
64
|
+
|
65
|
+
static VALUE metadata_s_register_ptype(VALUE klass, VALUE ptype)
|
66
|
+
{
|
67
|
+
rb_hash_aset(ptype_to_class, ptype, klass);
|
68
|
+
rb_hash_aset(class_to_ptype, klass, ptype);
|
69
|
+
return Qnil;
|
70
|
+
}
|
71
|
+
|
72
|
+
static VALUE metadata_get_ub1(VALUE self, VALUE idx)
|
73
|
+
{
|
74
|
+
oci8_base_t *base = DATA_PTR(self);
|
75
|
+
ub1 value = 0;
|
76
|
+
ub4 size = sizeof(value);
|
77
|
+
|
78
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
79
|
+
if (size != 1) {
|
80
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 1, but %d", size);
|
81
|
+
}
|
82
|
+
return INT2FIX(value);
|
83
|
+
}
|
84
|
+
|
85
|
+
static VALUE metadata_get_ub2(VALUE self, VALUE idx)
|
86
|
+
{
|
87
|
+
oci8_base_t *base = DATA_PTR(self);
|
88
|
+
ub2 value = 0;
|
89
|
+
ub4 size = sizeof(value);
|
90
|
+
|
91
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
92
|
+
if (size != 2) {
|
93
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 2, but %d", size);
|
94
|
+
}
|
95
|
+
return INT2FIX(value);
|
96
|
+
}
|
97
|
+
|
98
|
+
/* get ub2 without size check. */
|
99
|
+
static VALUE metadata_get_ub2_nc(VALUE self, VALUE idx)
|
100
|
+
{
|
101
|
+
oci8_base_t *base = DATA_PTR(self);
|
102
|
+
ub2 value = 0;
|
103
|
+
|
104
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, 0, FIX2INT(idx), oci8_errhp));
|
105
|
+
return INT2FIX(value);
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE metadata_get_ub4(VALUE self, VALUE idx)
|
109
|
+
{
|
110
|
+
oci8_base_t *base = DATA_PTR(self);
|
111
|
+
ub4 value = 0;
|
112
|
+
ub4 size = sizeof(value);
|
113
|
+
|
114
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
115
|
+
if (size != 4) {
|
116
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 4, but %d", size);
|
117
|
+
}
|
118
|
+
#if SIZEOF_LONG > 4
|
119
|
+
return INT2FIX(value);
|
120
|
+
#else
|
121
|
+
return UINT2NUM(value);
|
122
|
+
#endif
|
123
|
+
}
|
124
|
+
|
125
|
+
static VALUE metadata_get_sb1(VALUE self, VALUE idx)
|
126
|
+
{
|
127
|
+
oci8_base_t *base = DATA_PTR(self);
|
128
|
+
sb1 value = 0;
|
129
|
+
ub4 size = sizeof(value);
|
130
|
+
|
131
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
132
|
+
if (size != 1) {
|
133
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 1, but %d", size);
|
134
|
+
}
|
135
|
+
return INT2FIX(value);
|
136
|
+
}
|
137
|
+
|
138
|
+
static VALUE metadata_get_sb2(VALUE self, VALUE idx)
|
139
|
+
{
|
140
|
+
oci8_base_t *base = DATA_PTR(self);
|
141
|
+
sb2 value = 0;
|
142
|
+
ub4 size = sizeof(value);
|
143
|
+
|
144
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
145
|
+
if (size != 2) {
|
146
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 2, but %d", size);
|
147
|
+
}
|
148
|
+
return INT2FIX(value);
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE metadata_get_sb4(VALUE self, VALUE idx)
|
152
|
+
{
|
153
|
+
oci8_base_t *base = DATA_PTR(self);
|
154
|
+
sb4 value = 0;
|
155
|
+
ub4 size = sizeof(value);
|
156
|
+
|
157
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
158
|
+
if (size != 4) {
|
159
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 4, but %d", size);
|
160
|
+
}
|
161
|
+
#if SIZEOF_LONG > 4
|
162
|
+
return INT2FIX(value);
|
163
|
+
#else
|
164
|
+
return INT2NUM(value);
|
165
|
+
#endif
|
166
|
+
}
|
167
|
+
|
168
|
+
static VALUE metadata_get_text(VALUE self, VALUE idx)
|
169
|
+
{
|
170
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
171
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(md->svc);
|
172
|
+
text *value;
|
173
|
+
ub4 size;
|
174
|
+
|
175
|
+
/* remote call sometimes? */
|
176
|
+
oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
|
177
|
+
return rb_external_str_new_with_enc(TO_CHARPTR(value), size, oci8_encoding);
|
178
|
+
}
|
179
|
+
|
180
|
+
static VALUE metadata_get_oradate(VALUE self, VALUE idx)
|
181
|
+
{
|
182
|
+
oci8_base_t *base = DATA_PTR(self);
|
183
|
+
ub1 *value;
|
184
|
+
ub4 size = 7;
|
185
|
+
static VALUE cOraDate = Qnil;
|
186
|
+
VALUE obj;
|
187
|
+
|
188
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
189
|
+
if (size != 7) {
|
190
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect 7, but %d", size);
|
191
|
+
}
|
192
|
+
if (NIL_P(cOraDate))
|
193
|
+
cOraDate = rb_eval_string("OraDate");
|
194
|
+
obj = rb_funcall(cOraDate, oci8_id_new, 0);
|
195
|
+
memcpy(DATA_PTR(obj), value, 7);
|
196
|
+
return obj;
|
197
|
+
}
|
198
|
+
|
199
|
+
static VALUE metadata_get_oraint(VALUE self, VALUE idx)
|
200
|
+
{
|
201
|
+
oci8_base_t *base = DATA_PTR(self);
|
202
|
+
ub1 *value;
|
203
|
+
ub4 size = 21;
|
204
|
+
OCINumber on;
|
205
|
+
|
206
|
+
oci_lc(OCIAttrGet(base->hp.ptr, base->type, &value, &size, FIX2INT(idx), oci8_errhp));
|
207
|
+
if (size >= 22) {
|
208
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect less than 22, but %d", size);
|
209
|
+
}
|
210
|
+
memset(&on, 0, sizeof(on));
|
211
|
+
on.OCINumberPart[0] = size;
|
212
|
+
memcpy(&on.OCINumberPart[1], value, size);
|
213
|
+
return oci8_make_integer(&on);
|
214
|
+
}
|
215
|
+
|
216
|
+
static VALUE metadata_get_param(VALUE self, VALUE idx)
|
217
|
+
{
|
218
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
219
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(md->svc);
|
220
|
+
OCIParam *value;
|
221
|
+
ub4 size = sizeof(value);
|
222
|
+
|
223
|
+
/* remote call? */
|
224
|
+
oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
|
225
|
+
if (size != sizeof(OCIParam *)) {
|
226
|
+
rb_raise(rb_eRuntimeError, "Invalid attribute size. expect %d, but %d", (sb4)sizeof(OCIParam *), size);
|
227
|
+
}
|
228
|
+
return oci8_metadata_create(value, md->svc, self);
|
229
|
+
}
|
230
|
+
|
231
|
+
static VALUE metadata_get_param_at(VALUE self, VALUE idx)
|
232
|
+
{
|
233
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
234
|
+
OCIParam *value;
|
235
|
+
|
236
|
+
oci_lc(OCIParamGet(md->base.hp.ptr, md->base.type, oci8_errhp, (dvoid *)&value, FIX2INT(idx)));
|
237
|
+
return oci8_metadata_create(value, md->svc, self);
|
238
|
+
}
|
239
|
+
|
240
|
+
static VALUE metadata_get_charset_name(VALUE self, VALUE charset_id)
|
241
|
+
{
|
242
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
243
|
+
|
244
|
+
return oci8_charset_id2name(md->svc, charset_id);
|
245
|
+
}
|
246
|
+
|
247
|
+
static VALUE metadata_get_con(VALUE self)
|
248
|
+
{
|
249
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
250
|
+
return md->svc;
|
251
|
+
}
|
252
|
+
|
253
|
+
static VALUE metadata_is_implicit_p(VALUE self)
|
254
|
+
{
|
255
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
256
|
+
return md->is_implicit ? Qtrue : Qfalse;
|
257
|
+
}
|
258
|
+
|
259
|
+
static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype, VALUE klass, VALUE check_public)
|
260
|
+
{
|
261
|
+
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
262
|
+
OCIParam *parmhp;
|
263
|
+
VALUE type;
|
264
|
+
VALUE obj;
|
265
|
+
oci8_base_t *desc;
|
266
|
+
|
267
|
+
/* make a describe handle object */
|
268
|
+
obj = rb_obj_alloc(oci8_cOCIHandle);
|
269
|
+
desc = DATA_PTR(obj);
|
270
|
+
oci_lc(OCIHandleAlloc(oci8_envhp, (dvoid *)&desc->hp.dschp, OCI_HTYPE_DESCRIBE, 0, 0));
|
271
|
+
desc->type = OCI_HTYPE_DESCRIBE;
|
272
|
+
|
273
|
+
type = rb_hash_aref(class_to_ptype, klass);
|
274
|
+
if (RTEST(check_public)) {
|
275
|
+
sb4 val = -1;
|
276
|
+
/* size of OCI_ATTR_DESC_PUBLIC is undocumented. */
|
277
|
+
oci_lc(OCIAttrSet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &val, 0, OCI_ATTR_DESC_PUBLIC, oci8_errhp));
|
278
|
+
}
|
279
|
+
oci_lc(OCIDescribeAny_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, objptr, objlen,
|
280
|
+
objtype, OCI_DEFAULT, FIX2INT(type), desc->hp.dschp));
|
281
|
+
oci_lc(OCIAttrGet(desc->hp.dschp, OCI_HTYPE_DESCRIBE, &parmhp, 0, OCI_ATTR_PARAM, oci8_errhp));
|
282
|
+
return oci8_metadata_create(parmhp, self, obj);
|
283
|
+
}
|
284
|
+
|
285
|
+
static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_public)
|
286
|
+
{
|
287
|
+
OCI8SafeStringValue(name);
|
288
|
+
if (RSTRING_LEN(name) == 0) {
|
289
|
+
rb_raise(rb_eArgError, "empty string is set.");
|
290
|
+
}
|
291
|
+
return oci8_do_describe(self, RSTRING_PTR(name), RSTRING_LEN(name), OCI_OTYPE_NAME, klass, check_public);
|
292
|
+
}
|
293
|
+
|
294
|
+
static VALUE metadata_get_type_metadata(VALUE self, VALUE klass)
|
295
|
+
{
|
296
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
297
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(md->svc);
|
298
|
+
OCIRef *ref = NULL;
|
299
|
+
|
300
|
+
/* remote call */
|
301
|
+
oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp));
|
302
|
+
return oci8_do_describe(md->svc, ref, 0, OCI_OTYPE_REF, klass, Qfalse);
|
303
|
+
}
|
304
|
+
|
305
|
+
static VALUE metadata_get_tdo_id(VALUE self)
|
306
|
+
{
|
307
|
+
oci8_metadata_t *md = DATA_PTR(self);
|
308
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(md->svc);
|
309
|
+
OCIRef *tdo_ref = NULL;
|
310
|
+
void *tdo;
|
311
|
+
|
312
|
+
oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &tdo_ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp));
|
313
|
+
if (tdo_ref == NULL)
|
314
|
+
return Qnil;
|
315
|
+
oci_lc(OCIObjectPin_nb(svcctx, oci8_envhp, oci8_errhp, tdo_ref, 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, &tdo));
|
316
|
+
oci_lc(OCIObjectUnpin(oci8_envhp, oci8_errhp, tdo));
|
317
|
+
#if SIZEOF_LONG == SIZEOF_VOIDP
|
318
|
+
return ((VALUE)tdo | (VALUE)1);
|
319
|
+
#else
|
320
|
+
return LL2NUM(((LONG_LONG)tdo) >>1);
|
321
|
+
#endif
|
322
|
+
}
|
323
|
+
|
324
|
+
oci8_base_class_t oci8_metadata_class = {
|
325
|
+
oci8_metadata_mark,
|
326
|
+
NULL,
|
327
|
+
sizeof(oci8_metadata_t),
|
328
|
+
};
|
329
|
+
|
330
|
+
void Init_oci8_metadata(VALUE cOCI8)
|
331
|
+
{
|
332
|
+
mOCI8Metadata = rb_define_module_under(cOCI8, "Metadata");
|
333
|
+
cOCI8MetadataBase = oci8_define_class_under(mOCI8Metadata, "Base", &oci8_metadata_class);
|
334
|
+
ptype_to_class = rb_hash_new();
|
335
|
+
class_to_ptype = rb_hash_new();
|
336
|
+
rb_global_variable(&ptype_to_class);
|
337
|
+
rb_global_variable(&class_to_ptype);
|
338
|
+
|
339
|
+
rb_define_singleton_method(cOCI8MetadataBase, "register_ptype", metadata_s_register_ptype, 1);
|
340
|
+
rb_define_private_method(cOCI8MetadataBase, "__ub1", metadata_get_ub1, 1);
|
341
|
+
rb_define_private_method(cOCI8MetadataBase, "__ub2", metadata_get_ub2, 1);
|
342
|
+
rb_define_private_method(cOCI8MetadataBase, "__ub2_nc", metadata_get_ub2_nc, 1);
|
343
|
+
rb_define_private_method(cOCI8MetadataBase, "__ub4", metadata_get_ub4, 1);
|
344
|
+
rb_define_private_method(cOCI8MetadataBase, "__sb1", metadata_get_sb1, 1);
|
345
|
+
rb_define_private_method(cOCI8MetadataBase, "__sb2", metadata_get_sb2, 1);
|
346
|
+
rb_define_private_method(cOCI8MetadataBase, "__sb4", metadata_get_sb4, 1);
|
347
|
+
rb_define_private_method(cOCI8MetadataBase, "__text", metadata_get_text, 1);
|
348
|
+
rb_define_private_method(cOCI8MetadataBase, "__oradate", metadata_get_oradate, 1);
|
349
|
+
rb_define_private_method(cOCI8MetadataBase, "__oraint", metadata_get_oraint, 1);
|
350
|
+
rb_define_private_method(cOCI8MetadataBase, "__param", metadata_get_param, 1);
|
351
|
+
rb_define_private_method(cOCI8MetadataBase, "__param_at", metadata_get_param_at, 1);
|
352
|
+
rb_define_private_method(cOCI8MetadataBase, "__charset_name", metadata_get_charset_name, 1);
|
353
|
+
rb_define_private_method(cOCI8MetadataBase, "__con", metadata_get_con, 0);
|
354
|
+
rb_define_private_method(cOCI8MetadataBase, "__is_implicit?", metadata_is_implicit_p, 0);
|
355
|
+
|
356
|
+
rb_define_private_method(cOCI8, "__describe", oci8_describe, 3);
|
357
|
+
rb_define_private_method(cOCI8MetadataBase, "__type_metadata", metadata_get_type_metadata, 1);
|
358
|
+
rb_define_method(cOCI8MetadataBase, "tdo_id", metadata_get_tdo_id, 0);
|
359
|
+
}
|
data/ext/oci8/object.c
ADDED
@@ -0,0 +1,622 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Document-class: OCI8::TDO
|
4
|
+
*
|
5
|
+
* OCI8::TDO is the class for Type Descriptor Object, which describe
|
6
|
+
* Oracle's object type.
|
7
|
+
*
|
8
|
+
* An instance of OCI8::TDO is specific to the connection. This means
|
9
|
+
* One TDO instance for a connection is not available to another connection.
|
10
|
+
*/
|
11
|
+
#include "oci8.h"
|
12
|
+
#include <orid.h>
|
13
|
+
|
14
|
+
static VALUE cOCI8TDO;
|
15
|
+
static VALUE cOCI8NamedType;
|
16
|
+
static VALUE cOCI8NamedCollection;
|
17
|
+
static VALUE cOCI8BindNamedType;
|
18
|
+
static ID id_to_value;
|
19
|
+
static ID id_set_attributes;
|
20
|
+
|
21
|
+
typedef struct {
|
22
|
+
oci8_base_t base;
|
23
|
+
VALUE tdo;
|
24
|
+
char **instancep;
|
25
|
+
char **null_structp;
|
26
|
+
} oci8_named_type_t;
|
27
|
+
|
28
|
+
enum {
|
29
|
+
ATTR_INVALID = 0,
|
30
|
+
ATTR_STRING,
|
31
|
+
ATTR_RAW,
|
32
|
+
ATTR_OCINUMBER,
|
33
|
+
ATTR_FLOAT,
|
34
|
+
ATTR_INTEGER,
|
35
|
+
ATTR_BINARY_DOUBLE,
|
36
|
+
ATTR_BINARY_FLOAT,
|
37
|
+
ATTR_NAMED_TYPE,
|
38
|
+
ATTR_NAMED_COLLECTION,
|
39
|
+
};
|
40
|
+
|
41
|
+
static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data, OCIInd *ind);
|
42
|
+
static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data, OCIInd *ind, VALUE val);
|
43
|
+
|
44
|
+
static void oci8_tdo_mark(oci8_base_t *base)
|
45
|
+
{
|
46
|
+
if (base->parent != NULL) {
|
47
|
+
rb_gc_mark(base->parent->self);
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
static void oci8_tdo_free(oci8_base_t *base)
|
52
|
+
{
|
53
|
+
if (base->hp.tdo != NULL) {
|
54
|
+
OCIObjectUnpin(oci8_envhp, oci8_errhp, base->hp.tdo);
|
55
|
+
base->hp.tdo = NULL;
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
static VALUE oci8_tdo_setup(VALUE self, VALUE svc, VALUE md_obj)
|
60
|
+
{
|
61
|
+
oci8_base_t *tdo = DATA_PTR(self);
|
62
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(svc);
|
63
|
+
oci8_base_t *md;
|
64
|
+
OCIRef *tdo_ref = NULL;
|
65
|
+
|
66
|
+
Check_Object(md_obj, cOCI8MetadataBase);
|
67
|
+
md = DATA_PTR(md_obj);
|
68
|
+
|
69
|
+
if (tdo->hp.tdo != NULL) {
|
70
|
+
OCIObjectUnpin(oci8_envhp, oci8_errhp, tdo->hp.tdo);
|
71
|
+
tdo->hp.tdo = NULL;
|
72
|
+
}
|
73
|
+
oci_lc(OCIAttrGet(md->hp.ptr, OCI_DTYPE_PARAM, &tdo_ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp));
|
74
|
+
if (tdo_ref == NULL)
|
75
|
+
return Qnil;
|
76
|
+
oci_lc(OCIObjectPin_nb(svcctx, oci8_envhp, oci8_errhp, tdo_ref, 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, &tdo->hp.ptr));
|
77
|
+
oci8_link_to_parent(tdo, &svcctx->base);
|
78
|
+
return self;
|
79
|
+
}
|
80
|
+
|
81
|
+
static oci8_base_class_t oci8_tdo_class = {
|
82
|
+
oci8_tdo_mark,
|
83
|
+
oci8_tdo_free,
|
84
|
+
sizeof(oci8_base_t)
|
85
|
+
};
|
86
|
+
|
87
|
+
static void oci8_named_type_mark(oci8_base_t *base)
|
88
|
+
{
|
89
|
+
if (base->parent != NULL) {
|
90
|
+
rb_gc_mark(base->parent->self);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
static void oci8_named_type_free(oci8_base_t *base)
|
95
|
+
{
|
96
|
+
oci8_named_type_t *obj = (oci8_named_type_t *)base;
|
97
|
+
obj->instancep = NULL;
|
98
|
+
obj->null_structp = NULL;
|
99
|
+
}
|
100
|
+
|
101
|
+
static VALUE oci8_named_type_initialize(VALUE self)
|
102
|
+
{
|
103
|
+
oci8_named_type_t *obj = DATA_PTR(self);
|
104
|
+
|
105
|
+
obj->tdo = Qnil;
|
106
|
+
obj->instancep = NULL;
|
107
|
+
obj->null_structp = NULL;
|
108
|
+
return Qnil;
|
109
|
+
}
|
110
|
+
|
111
|
+
static VALUE oci8_named_type_tdo(VALUE self)
|
112
|
+
{
|
113
|
+
oci8_named_type_t *obj = DATA_PTR(self);
|
114
|
+
return obj->tdo;
|
115
|
+
}
|
116
|
+
|
117
|
+
static void oci8_named_type_check_offset(VALUE self, VALUE val_offset, VALUE ind_offset, size_t val_size, void **instancep, OCIInd **indp)
|
118
|
+
{
|
119
|
+
oci8_named_type_t *obj = DATA_PTR(self);
|
120
|
+
if (obj->instancep == NULL || obj->null_structp == NULL) {
|
121
|
+
rb_raise(rb_eRuntimeError, "%s is not initialized or freed", rb_obj_classname(self));
|
122
|
+
}
|
123
|
+
Check_Type(val_offset, T_FIXNUM);
|
124
|
+
Check_Type(ind_offset, T_FIXNUM);
|
125
|
+
*instancep = (void*)(*obj->instancep + FIX2INT(val_offset));
|
126
|
+
*indp = (OCIInd *)(*obj->null_structp + FIX2INT(ind_offset));
|
127
|
+
}
|
128
|
+
|
129
|
+
/*
|
130
|
+
* attribute
|
131
|
+
*/
|
132
|
+
static VALUE oci8_named_type_get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, VALUE val_offset, VALUE ind_offset)
|
133
|
+
{
|
134
|
+
void *data;
|
135
|
+
OCIInd *ind;
|
136
|
+
|
137
|
+
oci8_named_type_check_offset(self, val_offset, ind_offset, sizeof(OCIString*), &data, &ind);
|
138
|
+
return get_attribute(self, datatype, typeinfo, data, ind);
|
139
|
+
}
|
140
|
+
|
141
|
+
static VALUE get_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data, OCIInd *ind)
|
142
|
+
{
|
143
|
+
VALUE rv;
|
144
|
+
VALUE tmp_obj;
|
145
|
+
oci8_named_type_t *obj;
|
146
|
+
|
147
|
+
if (*ind) {
|
148
|
+
return Qnil;
|
149
|
+
}
|
150
|
+
Check_Type(datatype, T_FIXNUM);
|
151
|
+
switch (FIX2INT(datatype)) {
|
152
|
+
case ATTR_STRING:
|
153
|
+
return rb_external_str_new_with_enc(TO_CHARPTR(OCIStringPtr(oci8_envhp, *(OCIString **)data)),
|
154
|
+
OCIStringSize(oci8_envhp, *(OCIString **)data),
|
155
|
+
oci8_encoding);
|
156
|
+
case ATTR_RAW:
|
157
|
+
return rb_str_new(TO_CHARPTR(OCIRawPtr(oci8_envhp, *(OCIRaw **)data)),
|
158
|
+
OCIRawSize(oci8_envhp, *(OCIRaw **)data));
|
159
|
+
case ATTR_OCINUMBER:
|
160
|
+
return oci8_make_ocinumber((OCINumber *)data);
|
161
|
+
case ATTR_FLOAT:
|
162
|
+
return oci8_make_float((OCINumber *)data);
|
163
|
+
case ATTR_INTEGER:
|
164
|
+
return oci8_make_integer((OCINumber *)data);
|
165
|
+
case ATTR_BINARY_DOUBLE:
|
166
|
+
return rb_float_new(*(double*)data);
|
167
|
+
case ATTR_BINARY_FLOAT:
|
168
|
+
return rb_float_new((double)*(float*)data);
|
169
|
+
case ATTR_NAMED_TYPE:
|
170
|
+
Check_Object(typeinfo, cOCI8TDO);
|
171
|
+
/* Be carefull. Don't use *tmp_obj* out of this function. */
|
172
|
+
tmp_obj = rb_funcall(cOCI8NamedType, oci8_id_new, 0);
|
173
|
+
obj = DATA_PTR(tmp_obj);
|
174
|
+
obj->tdo = typeinfo;
|
175
|
+
obj->instancep = (char**)&data;
|
176
|
+
obj->null_structp = (char**)&ind;
|
177
|
+
oci8_link_to_parent(&obj->base, DATA_PTR(self));
|
178
|
+
rv = rb_funcall(tmp_obj, id_to_value, 0);
|
179
|
+
oci8_unlink_from_parent(&obj->base);
|
180
|
+
return rv;
|
181
|
+
case ATTR_NAMED_COLLECTION:
|
182
|
+
Check_Object(typeinfo, cOCI8TDO);
|
183
|
+
/* Be carefull. Don't use *tmp_obj* out of this function. */
|
184
|
+
tmp_obj = rb_funcall(cOCI8NamedCollection, oci8_id_new, 0);
|
185
|
+
obj = DATA_PTR(tmp_obj);
|
186
|
+
obj->tdo = typeinfo;
|
187
|
+
obj->instancep = (char**)data;
|
188
|
+
obj->null_structp = (char**)&ind;
|
189
|
+
oci8_link_to_parent(&obj->base, DATA_PTR(self));
|
190
|
+
rv = rb_funcall(tmp_obj, id_to_value, 0);
|
191
|
+
oci8_unlink_from_parent(&obj->base);
|
192
|
+
return rv;
|
193
|
+
default:
|
194
|
+
rb_raise(rb_eRuntimeError, "not supported datatype");
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
198
|
+
static VALUE oci8_named_coll_get_coll_element(VALUE self, VALUE datatype, VALUE typeinfo)
|
199
|
+
{
|
200
|
+
oci8_named_type_t *obj = DATA_PTR(self);
|
201
|
+
OCIColl *coll;
|
202
|
+
void *data;
|
203
|
+
OCIInd *ind;
|
204
|
+
VALUE ary;
|
205
|
+
sb4 size;
|
206
|
+
sb4 idx;
|
207
|
+
|
208
|
+
if (obj->instancep == NULL || obj->null_structp == NULL) {
|
209
|
+
rb_raise(rb_eRuntimeError, "%s is not initialized or freed", rb_obj_classname(self));
|
210
|
+
}
|
211
|
+
coll = (OCIColl*)*obj->instancep;
|
212
|
+
ind = (OCIInd*)*obj->null_structp;
|
213
|
+
if (*ind) {
|
214
|
+
return Qnil;
|
215
|
+
}
|
216
|
+
oci_lc(OCICollSize(oci8_envhp, oci8_errhp, coll, &size));
|
217
|
+
ary = rb_ary_new2(size);
|
218
|
+
for (idx = 0; idx < size; idx++) {
|
219
|
+
boolean exists;
|
220
|
+
oci_lc(OCICollGetElem(oci8_envhp, oci8_errhp, coll, idx, &exists, &data, (dvoid**)&ind));
|
221
|
+
if (exists) {
|
222
|
+
void *tmp;
|
223
|
+
if (datatype == INT2FIX(ATTR_NAMED_COLLECTION)) {
|
224
|
+
tmp = data;
|
225
|
+
data = &tmp;
|
226
|
+
}
|
227
|
+
rb_ary_store(ary, idx, get_attribute(self, datatype, typeinfo, data, ind));
|
228
|
+
}
|
229
|
+
}
|
230
|
+
return ary;
|
231
|
+
}
|
232
|
+
|
233
|
+
static VALUE oci8_named_type_set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, VALUE val_offset, VALUE ind_offset, VALUE val)
|
234
|
+
{
|
235
|
+
void *data;
|
236
|
+
OCIInd *ind;
|
237
|
+
|
238
|
+
oci8_named_type_check_offset(self, val_offset, ind_offset, sizeof(OCIString*), &data, &ind);
|
239
|
+
set_attribute(self, datatype, typeinfo, data, ind, val);
|
240
|
+
return Qnil;
|
241
|
+
}
|
242
|
+
|
243
|
+
typedef struct {
|
244
|
+
VALUE self;
|
245
|
+
VALUE datatype;
|
246
|
+
VALUE typeinfo;
|
247
|
+
VALUE val;
|
248
|
+
OCIColl *coll;
|
249
|
+
union {
|
250
|
+
void *ptr;
|
251
|
+
OCINumber num;
|
252
|
+
double dbl;
|
253
|
+
float flt;
|
254
|
+
} data;
|
255
|
+
OCIInd ind; /* for data.num, data.dbl, data.flt */
|
256
|
+
OCIInd *indp;
|
257
|
+
} set_coll_element_cb_data_t;
|
258
|
+
|
259
|
+
static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data);
|
260
|
+
static VALUE set_coll_element_ensure(set_coll_element_cb_data_t *cb_data);
|
261
|
+
|
262
|
+
static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE typeinfo, VALUE val)
|
263
|
+
{
|
264
|
+
oci8_named_type_t *obj = DATA_PTR(self);
|
265
|
+
OCIInd *ind;
|
266
|
+
set_coll_element_cb_data_t cb_data;
|
267
|
+
oci8_base_t *tdo;
|
268
|
+
oci8_base_t *svcctx;
|
269
|
+
|
270
|
+
if (obj->instancep == NULL || obj->null_structp == NULL) {
|
271
|
+
rb_raise(rb_eRuntimeError, "%s is not initialized or freed", rb_obj_classname(self));
|
272
|
+
}
|
273
|
+
Check_Type(datatype, T_FIXNUM);
|
274
|
+
ind = (OCIInd*)*obj->null_structp;
|
275
|
+
if (NIL_P(val)) {
|
276
|
+
*ind = -1;
|
277
|
+
return Qnil;
|
278
|
+
}
|
279
|
+
Check_Type(val, T_ARRAY);
|
280
|
+
/* search svcctx */
|
281
|
+
svcctx = DATA_PTR(obj->tdo);
|
282
|
+
while (svcctx->type != OCI_HTYPE_SVCCTX) {
|
283
|
+
svcctx = svcctx->parent;
|
284
|
+
}
|
285
|
+
/* setup cb_data */
|
286
|
+
memset(&cb_data, 0, sizeof(cb_data));
|
287
|
+
cb_data.self = self;
|
288
|
+
cb_data.datatype = datatype;
|
289
|
+
cb_data.typeinfo = typeinfo;
|
290
|
+
cb_data.val = val;
|
291
|
+
cb_data.coll = (OCIColl*)*obj->instancep;
|
292
|
+
switch (FIX2INT(datatype)) {
|
293
|
+
case ATTR_STRING:
|
294
|
+
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_VARCHAR2, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
295
|
+
oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
|
296
|
+
break;
|
297
|
+
case ATTR_RAW:
|
298
|
+
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_RAW, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
299
|
+
oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
|
300
|
+
break;
|
301
|
+
case ATTR_OCINUMBER:
|
302
|
+
case ATTR_FLOAT:
|
303
|
+
case ATTR_INTEGER:
|
304
|
+
OCINumberSetZero(oci8_errhp, &cb_data.data.num);
|
305
|
+
cb_data.indp = &cb_data.ind;
|
306
|
+
break;
|
307
|
+
case ATTR_BINARY_DOUBLE:
|
308
|
+
cb_data.data.dbl = 0.0;
|
309
|
+
cb_data.indp = &cb_data.ind;
|
310
|
+
break;
|
311
|
+
case ATTR_BINARY_FLOAT:
|
312
|
+
cb_data.data.flt = 0.0;
|
313
|
+
cb_data.indp = &cb_data.ind;
|
314
|
+
break;
|
315
|
+
case ATTR_NAMED_TYPE:
|
316
|
+
Check_Object(typeinfo, cOCI8TDO);
|
317
|
+
tdo = DATA_PTR(typeinfo);
|
318
|
+
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_OBJECT, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
319
|
+
oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
|
320
|
+
break;
|
321
|
+
case ATTR_NAMED_COLLECTION:
|
322
|
+
Check_Object(typeinfo, cOCI8TDO);
|
323
|
+
tdo = DATA_PTR(typeinfo);
|
324
|
+
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_NAMEDCOLLECTION, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
325
|
+
oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
|
326
|
+
break;
|
327
|
+
default:
|
328
|
+
rb_raise(rb_eRuntimeError, "not supported datatype");
|
329
|
+
}
|
330
|
+
#if 0
|
331
|
+
/* TODO: */
|
332
|
+
rb_ensure(set_coll_element_func, (VALUE)&cb_data, set_coll_element_ensure, (VALUE)&cb_data);
|
333
|
+
#else
|
334
|
+
set_coll_element_func(&cb_data);
|
335
|
+
set_coll_element_ensure(&cb_data);
|
336
|
+
#endif
|
337
|
+
return Qnil;
|
338
|
+
}
|
339
|
+
|
340
|
+
static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data)
|
341
|
+
{
|
342
|
+
VALUE self = cb_data->self;
|
343
|
+
VALUE val = cb_data->val;
|
344
|
+
VALUE datatype = cb_data->datatype;
|
345
|
+
VALUE typeinfo = cb_data->typeinfo;
|
346
|
+
OCIColl *coll = cb_data->coll;
|
347
|
+
sb4 size;
|
348
|
+
sb4 idx;
|
349
|
+
void *elem_ptr;
|
350
|
+
|
351
|
+
oci_lc(OCICollSize(oci8_envhp, oci8_errhp, coll, &size));
|
352
|
+
if (RARRAY_LEN(val) < size) {
|
353
|
+
oci_lc(OCICollTrim(oci8_envhp, oci8_errhp, size - RARRAY_LEN(val), coll));
|
354
|
+
}
|
355
|
+
for (idx = 0; idx < RARRAY_LEN(val); idx++) {
|
356
|
+
switch (FIX2INT(datatype)) {
|
357
|
+
case ATTR_NAMED_TYPE:
|
358
|
+
set_attribute(self, datatype, typeinfo, cb_data->data.ptr, cb_data->indp, RARRAY_PTR(val)[idx]);
|
359
|
+
break;
|
360
|
+
default:
|
361
|
+
set_attribute(self, datatype, typeinfo, (void*)&cb_data->data, cb_data->indp, RARRAY_PTR(val)[idx]);
|
362
|
+
break;
|
363
|
+
}
|
364
|
+
switch (FIX2INT(datatype)) {
|
365
|
+
case ATTR_OCINUMBER:
|
366
|
+
case ATTR_FLOAT:
|
367
|
+
case ATTR_INTEGER:
|
368
|
+
case ATTR_BINARY_DOUBLE:
|
369
|
+
case ATTR_BINARY_FLOAT:
|
370
|
+
elem_ptr = &cb_data->data;
|
371
|
+
break;
|
372
|
+
default:
|
373
|
+
elem_ptr = cb_data->data.ptr;
|
374
|
+
break;
|
375
|
+
}
|
376
|
+
if (idx < size) {
|
377
|
+
oci_lc(OCICollAssignElem(oci8_envhp, oci8_errhp, idx, elem_ptr, cb_data->indp, cb_data->coll));
|
378
|
+
} else {
|
379
|
+
oci_lc(OCICollAppend(oci8_envhp, oci8_errhp, elem_ptr, cb_data->indp, coll));
|
380
|
+
}
|
381
|
+
}
|
382
|
+
return Qnil;
|
383
|
+
}
|
384
|
+
|
385
|
+
static VALUE set_coll_element_ensure(set_coll_element_cb_data_t *cb_data)
|
386
|
+
{
|
387
|
+
VALUE datatype = cb_data->datatype;
|
388
|
+
|
389
|
+
switch (FIX2INT(datatype)) {
|
390
|
+
case ATTR_STRING:
|
391
|
+
case ATTR_RAW:
|
392
|
+
case ATTR_NAMED_TYPE:
|
393
|
+
case ATTR_NAMED_COLLECTION:
|
394
|
+
if (cb_data->data.ptr != NULL) {
|
395
|
+
OCIObjectFree(oci8_envhp, oci8_errhp, cb_data->data.ptr, OCI_DEFAULT);
|
396
|
+
}
|
397
|
+
break;
|
398
|
+
case ATTR_OCINUMBER:
|
399
|
+
case ATTR_FLOAT:
|
400
|
+
case ATTR_INTEGER:
|
401
|
+
case ATTR_BINARY_DOUBLE:
|
402
|
+
case ATTR_BINARY_FLOAT:
|
403
|
+
break;
|
404
|
+
}
|
405
|
+
return Qnil;
|
406
|
+
}
|
407
|
+
|
408
|
+
|
409
|
+
static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data, OCIInd *ind, VALUE val)
|
410
|
+
{
|
411
|
+
VALUE tmp_obj;
|
412
|
+
oci8_named_type_t *obj;
|
413
|
+
|
414
|
+
if (NIL_P(val)) {
|
415
|
+
*ind = -1;
|
416
|
+
return;
|
417
|
+
}
|
418
|
+
Check_Type(datatype, T_FIXNUM);
|
419
|
+
switch (FIX2INT(datatype)) {
|
420
|
+
case ATTR_STRING:
|
421
|
+
OCI8StringValue(val);
|
422
|
+
oci_lc(OCIStringAssignText(oci8_envhp, oci8_errhp,
|
423
|
+
RSTRING_ORATEXT(val), RSTRING_LEN(val),
|
424
|
+
(OCIString **)data));
|
425
|
+
break;
|
426
|
+
case ATTR_RAW:
|
427
|
+
StringValue(val);
|
428
|
+
oci_lc(OCIRawAssignBytes(oci8_envhp, oci8_errhp,
|
429
|
+
RSTRING_ORATEXT(val), RSTRING_LEN(val),
|
430
|
+
(OCIRaw **)data));
|
431
|
+
break;
|
432
|
+
case ATTR_OCINUMBER:
|
433
|
+
case ATTR_FLOAT:
|
434
|
+
oci8_set_ocinumber((OCINumber*)data, val);
|
435
|
+
break;
|
436
|
+
case ATTR_INTEGER:
|
437
|
+
oci8_set_integer((OCINumber*)data, val);
|
438
|
+
break;
|
439
|
+
case ATTR_BINARY_DOUBLE:
|
440
|
+
*(double*)data = NUM2DBL(val);
|
441
|
+
break;
|
442
|
+
case ATTR_BINARY_FLOAT:
|
443
|
+
*(float*)data = (float)NUM2DBL(val);
|
444
|
+
break;
|
445
|
+
case ATTR_NAMED_TYPE:
|
446
|
+
Check_Object(typeinfo, cOCI8TDO);
|
447
|
+
/* Be carefull. Don't use *tmp_obj* out of this function. */
|
448
|
+
tmp_obj = rb_funcall(cOCI8NamedType, oci8_id_new, 0);
|
449
|
+
obj = DATA_PTR(tmp_obj);
|
450
|
+
obj->tdo = typeinfo;
|
451
|
+
obj->instancep = (char**)&data;
|
452
|
+
obj->null_structp = (char**)&ind;
|
453
|
+
oci8_link_to_parent(&obj->base, DATA_PTR(self));
|
454
|
+
rb_funcall(tmp_obj, id_set_attributes, 1, val);
|
455
|
+
oci8_unlink_from_parent(&obj->base);
|
456
|
+
break;
|
457
|
+
case ATTR_NAMED_COLLECTION:
|
458
|
+
Check_Object(typeinfo, cOCI8TDO);
|
459
|
+
/* Be carefull. Don't use *tmp_obj* out of this function. */
|
460
|
+
tmp_obj = rb_funcall(cOCI8NamedCollection, oci8_id_new, 0);
|
461
|
+
obj = DATA_PTR(tmp_obj);
|
462
|
+
obj->tdo = typeinfo;
|
463
|
+
obj->instancep = (char**)data;
|
464
|
+
obj->null_structp = (char**)&ind;
|
465
|
+
oci8_link_to_parent(&obj->base, DATA_PTR(self));
|
466
|
+
rb_funcall(tmp_obj, id_set_attributes, 1, val);
|
467
|
+
oci8_unlink_from_parent(&obj->base);
|
468
|
+
break;
|
469
|
+
default:
|
470
|
+
rb_raise(rb_eRuntimeError, "not supported datatype");
|
471
|
+
}
|
472
|
+
*ind = 0;
|
473
|
+
}
|
474
|
+
|
475
|
+
static oci8_base_class_t oci8_named_type_class = {
|
476
|
+
oci8_named_type_mark,
|
477
|
+
oci8_named_type_free,
|
478
|
+
sizeof(oci8_named_type_t)
|
479
|
+
};
|
480
|
+
|
481
|
+
static void bind_named_type_mark(oci8_base_t *base)
|
482
|
+
{
|
483
|
+
oci8_bind_t *obind = (oci8_bind_t *)base;
|
484
|
+
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
485
|
+
ub4 idx = 0;
|
486
|
+
|
487
|
+
do {
|
488
|
+
rb_gc_mark(oho[idx].obj);
|
489
|
+
} while (++idx < obind->maxar_sz);
|
490
|
+
rb_gc_mark(obind->tdo);
|
491
|
+
}
|
492
|
+
|
493
|
+
static void bind_named_type_free(oci8_base_t *base)
|
494
|
+
{
|
495
|
+
oci8_bind_t *obind = (oci8_bind_t *)base;
|
496
|
+
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
497
|
+
ub4 idx = 0;
|
498
|
+
|
499
|
+
do {
|
500
|
+
if (oho[idx].hp != NULL) {
|
501
|
+
OCIObjectFree(oci8_envhp, oci8_errhp, oho[idx].hp, OCI_DEFAULT);
|
502
|
+
oho[idx].hp = NULL;
|
503
|
+
}
|
504
|
+
} while (++idx < obind->maxar_sz);
|
505
|
+
}
|
506
|
+
|
507
|
+
static VALUE bind_named_type_get(oci8_bind_t *obind, void *data, void *null_struct)
|
508
|
+
{
|
509
|
+
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)data;
|
510
|
+
return oho->obj;
|
511
|
+
}
|
512
|
+
|
513
|
+
static void bind_named_type_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
|
514
|
+
{
|
515
|
+
rb_raise(rb_eRuntimeError, "not supported");
|
516
|
+
}
|
517
|
+
|
518
|
+
static void bind_named_type_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
|
519
|
+
{
|
520
|
+
VALUE tdo_obj = length;
|
521
|
+
|
522
|
+
obind->value_sz = sizeof(void*);
|
523
|
+
obind->alloc_sz = sizeof(oci8_hp_obj_t);
|
524
|
+
|
525
|
+
Check_Object(tdo_obj, cOCI8TDO);
|
526
|
+
obind->tdo = tdo_obj;
|
527
|
+
}
|
528
|
+
|
529
|
+
static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
|
530
|
+
{
|
531
|
+
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
532
|
+
oci8_base_t *tdo = DATA_PTR(obind->tdo);
|
533
|
+
OCITypeCode tc = OCITypeTypeCode(oci8_envhp, oci8_errhp, tdo->hp.tdo);
|
534
|
+
VALUE klass = Qnil;
|
535
|
+
oci8_named_type_t *obj;
|
536
|
+
oci8_svcctx_t *svcctx;
|
537
|
+
ub4 idx = 0;
|
538
|
+
|
539
|
+
switch (tc) {
|
540
|
+
case OCI_TYPECODE_OBJECT:
|
541
|
+
klass = cOCI8NamedType;
|
542
|
+
break;
|
543
|
+
case OCI_TYPECODE_NAMEDCOLLECTION:
|
544
|
+
klass = cOCI8NamedCollection;
|
545
|
+
break;
|
546
|
+
}
|
547
|
+
svcctx = oci8_get_svcctx(svc);
|
548
|
+
do {
|
549
|
+
oho[idx].obj = rb_funcall(klass, oci8_id_new, 0);
|
550
|
+
obj = DATA_PTR(oho[idx].obj);
|
551
|
+
obj->tdo = obind->tdo;
|
552
|
+
obj->instancep = (char**)&oho[idx].hp;
|
553
|
+
obj->null_structp = (char**)&obind->u.null_structs[idx];
|
554
|
+
oci8_link_to_parent(&obj->base, &obind->base);
|
555
|
+
|
556
|
+
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->base.hp.svc, tc, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, (dvoid**)obj->instancep));
|
557
|
+
oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, (dvoid*)*obj->instancep, (dvoid**)obj->null_structp));
|
558
|
+
} while (++idx < obind->maxar_sz);
|
559
|
+
}
|
560
|
+
|
561
|
+
static const oci8_bind_class_t bind_named_type_class = {
|
562
|
+
{
|
563
|
+
bind_named_type_mark,
|
564
|
+
bind_named_type_free,
|
565
|
+
sizeof(oci8_bind_t)
|
566
|
+
},
|
567
|
+
bind_named_type_get,
|
568
|
+
bind_named_type_set,
|
569
|
+
bind_named_type_init,
|
570
|
+
bind_named_type_init_elem,
|
571
|
+
NULL,
|
572
|
+
NULL,
|
573
|
+
NULL,
|
574
|
+
SQLT_NTY
|
575
|
+
};
|
576
|
+
|
577
|
+
void Init_oci_object(VALUE cOCI8)
|
578
|
+
{
|
579
|
+
id_to_value = rb_intern("to_value");
|
580
|
+
id_set_attributes = rb_intern("attributes=");
|
581
|
+
|
582
|
+
/* OCI8::TDO */
|
583
|
+
cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &oci8_tdo_class);
|
584
|
+
rb_define_private_method(cOCI8TDO, "setup", oci8_tdo_setup, 2);
|
585
|
+
rb_define_const(cOCI8TDO, "ATTR_STRING", INT2FIX(ATTR_STRING));
|
586
|
+
rb_define_const(cOCI8TDO, "ATTR_RAW", INT2FIX(ATTR_RAW));
|
587
|
+
rb_define_const(cOCI8TDO, "ATTR_OCINUMBER", INT2FIX(ATTR_OCINUMBER));
|
588
|
+
rb_define_const(cOCI8TDO, "ATTR_FLOAT", INT2FIX(ATTR_FLOAT));
|
589
|
+
rb_define_const(cOCI8TDO, "ATTR_INTEGER", INT2FIX(ATTR_INTEGER));
|
590
|
+
rb_define_const(cOCI8TDO, "ATTR_BINARY_DOUBLE", INT2FIX(ATTR_BINARY_DOUBLE));
|
591
|
+
rb_define_const(cOCI8TDO, "ATTR_BINARY_FLOAT", INT2FIX(ATTR_BINARY_FLOAT));
|
592
|
+
rb_define_const(cOCI8TDO, "ATTR_NAMED_TYPE", INT2FIX(ATTR_NAMED_TYPE));
|
593
|
+
rb_define_const(cOCI8TDO, "ATTR_NAMED_COLLECTION", INT2FIX(ATTR_NAMED_COLLECTION));
|
594
|
+
#define ALIGNMENT_OF(type) (size_t)&(((struct {char c; type t;}*)0)->t)
|
595
|
+
rb_define_const(cOCI8TDO, "SIZE_OF_POINTER", INT2FIX(sizeof(void *)));
|
596
|
+
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_POINTER", INT2FIX(ALIGNMENT_OF(void *)));
|
597
|
+
rb_define_const(cOCI8TDO, "SIZE_OF_OCINUMBER", INT2FIX(sizeof(OCINumber)));
|
598
|
+
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_OCINUMBER", INT2FIX(ALIGNMENT_OF(OCINumber)));
|
599
|
+
rb_define_const(cOCI8TDO, "SIZE_OF_OCIDATE", INT2FIX(sizeof(OCIDate)));
|
600
|
+
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_OCIDATE", INT2FIX(ALIGNMENT_OF(OCIDate)));
|
601
|
+
rb_define_const(cOCI8TDO, "SIZE_OF_FLOAT", INT2FIX(sizeof(float)));
|
602
|
+
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_FLOAT", INT2FIX(ALIGNMENT_OF(float)));
|
603
|
+
rb_define_const(cOCI8TDO, "SIZE_OF_DOUBLE", INT2FIX(sizeof(double)));
|
604
|
+
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_DOUBLE", INT2FIX(ALIGNMENT_OF(double)));
|
605
|
+
|
606
|
+
/* OCI8::NamedType */
|
607
|
+
cOCI8NamedType = oci8_define_class_under(cOCI8, "NamedType", &oci8_named_type_class);
|
608
|
+
rb_define_method(cOCI8NamedType, "initialize", oci8_named_type_initialize, 0);
|
609
|
+
rb_define_method(cOCI8NamedType, "tdo", oci8_named_type_tdo, 0);
|
610
|
+
rb_define_private_method(cOCI8NamedType, "get_attribute", oci8_named_type_get_attribute, 4);
|
611
|
+
rb_define_private_method(cOCI8NamedType, "set_attribute", oci8_named_type_set_attribute, 5);
|
612
|
+
|
613
|
+
/* OCI8::NamedCollection */
|
614
|
+
cOCI8NamedCollection = oci8_define_class_under(cOCI8, "NamedCollection", &oci8_named_type_class);
|
615
|
+
rb_define_method(cOCI8NamedCollection, "initialize", oci8_named_type_initialize, 0);
|
616
|
+
rb_define_method(cOCI8NamedCollection, "tdo", oci8_named_type_tdo, 0);
|
617
|
+
rb_define_private_method(cOCI8NamedCollection, "get_coll_element", oci8_named_coll_get_coll_element, 2);
|
618
|
+
rb_define_private_method(cOCI8NamedCollection, "set_coll_element", oci8_named_coll_set_coll_element, 3);
|
619
|
+
|
620
|
+
/* OCI8::BindType::NamedType */
|
621
|
+
cOCI8BindNamedType = oci8_define_bind_class("NamedType", &bind_named_type_class);
|
622
|
+
}
|