ruby-oci8 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/ChangeLog +366 -19
  2. data/Makefile +2 -8
  3. data/NEWS +111 -0
  4. data/README +4 -85
  5. data/VERSION +1 -1
  6. data/dist-files +9 -2
  7. data/ext/oci8/.document +1 -0
  8. data/ext/oci8/apiwrap.c.tmpl +12 -2
  9. data/ext/oci8/apiwrap.yml +37 -21
  10. data/ext/oci8/attr.c +23 -74
  11. data/ext/oci8/bind.c +93 -225
  12. data/ext/oci8/connection_pool.c +201 -0
  13. data/ext/oci8/encoding.c +117 -24
  14. data/ext/oci8/env.c +5 -10
  15. data/ext/oci8/error.c +171 -189
  16. data/ext/oci8/extconf.rb +6 -2
  17. data/ext/oci8/lob.c +81 -79
  18. data/ext/oci8/metadata.c +42 -177
  19. data/ext/oci8/object.c +55 -28
  20. data/ext/oci8/oci8.c +426 -294
  21. data/ext/oci8/oci8.h +84 -51
  22. data/ext/oci8/oci8lib.c +75 -53
  23. data/ext/oci8/ocidatetime.c +67 -88
  24. data/ext/oci8/ocihandle.c +78 -37
  25. data/ext/oci8/ocinumber.c +166 -109
  26. data/ext/oci8/oraconf.rb +68 -157
  27. data/ext/oci8/oradate.c +2 -7
  28. data/ext/oci8/stmt.c +40 -183
  29. data/ext/oci8/thread_util.c +85 -0
  30. data/ext/oci8/thread_util.h +30 -0
  31. data/lib/oci8.rb.in +19 -13
  32. data/lib/oci8/.document +2 -0
  33. data/lib/oci8/bindtype.rb +62 -45
  34. data/lib/oci8/connection_pool.rb +118 -0
  35. data/lib/oci8/datetime.rb +304 -320
  36. data/lib/oci8/encoding-init.rb +62 -30
  37. data/lib/oci8/encoding.yml +3 -3
  38. data/lib/oci8/metadata.rb +552 -497
  39. data/lib/oci8/object.rb +9 -9
  40. data/lib/oci8/oci8.rb +161 -2
  41. data/lib/oci8/ocihandle.rb +427 -0
  42. data/lib/oci8/properties.rb +31 -1
  43. data/ruby-oci8.gemspec +10 -3
  44. data/test/README +41 -3
  45. data/test/config.rb +16 -0
  46. data/test/test_all.rb +3 -0
  47. data/test/test_bind_string.rb +106 -0
  48. data/test/test_break.rb +33 -7
  49. data/test/test_clob.rb +13 -10
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +2 -2
  52. data/test/test_datetime.rb +26 -66
  53. data/test/test_encoding.rb +7 -3
  54. data/test/test_error.rb +88 -0
  55. data/test/test_metadata.rb +1356 -204
  56. data/test/test_oci8.rb +27 -8
  57. data/test/test_oranumber.rb +41 -0
  58. metadata +34 -9
  59. data/ext/oci8/xmldb.c +0 -383
@@ -2,19 +2,31 @@
2
2
  /*
3
3
  * bind.c
4
4
  *
5
- * $Author: kubo $
6
- * $Date: 2010-12-14 20:30:44 +0900 (Tue, 14 Dec 2010) $
7
- *
8
- * Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
9
6
  */
10
7
  #include "oci8.h"
11
8
 
9
+ #ifndef OCI_ATTR_MAXCHAR_SIZE
10
+ #define OCI_ATTR_MAXCHAR_SIZE 164
11
+ #endif
12
+
12
13
  static ID id_bind_type;
14
+ static VALUE sym_length;
15
+ static VALUE sym_length_semantics;
16
+ static VALUE sym_char;
17
+ static VALUE sym_nchar;
13
18
 
14
19
  static VALUE cOCI8BindTypeBase;
15
20
 
21
+ typedef struct {
22
+ oci8_bind_t obind;
23
+ sb4 bytelen;
24
+ sb4 charlen;
25
+ ub1 csfrm;
26
+ } oci8_bind_string_t;
27
+
16
28
  /*
17
- * bind_char and bind_nchar
29
+ * bind_string
18
30
  */
19
31
  static VALUE bind_string_get(oci8_bind_t *obind, void *data, void *null_struct)
20
32
  {
@@ -24,67 +36,87 @@ static VALUE bind_string_get(oci8_bind_t *obind, void *data, void *null_struct)
24
36
 
25
37
  static void bind_string_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
26
38
  {
39
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
27
40
  oci8_vstr_t *vstr = (oci8_vstr_t *)data;
28
41
 
29
42
  OCI8StringValue(val);
30
- if (RSTRING_LEN(val) > obind->value_sz - sizeof(vstr->size)) {
31
- rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obind->value_sz - (sb4)sizeof(vstr->size));
43
+ if (RSTRING_LEN(val) > obs->bytelen) {
44
+ rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
32
45
  }
33
46
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
34
47
  vstr->size = RSTRING_LEN(val);
35
48
  }
36
49
 
37
- static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
50
+ static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
38
51
  {
52
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
53
+ VALUE length;
54
+ VALUE length_semantics;
55
+ VALUE nchar;
39
56
  sb4 sz;
40
- if (NIL_P(length)) {
41
- if (NIL_P(val)) {
42
- rb_raise(rb_eArgError, "value and length are both null.");
57
+
58
+ Check_Type(param, T_HASH);
59
+ length = rb_hash_aref(param, sym_length);
60
+ length_semantics = rb_hash_aref(param, sym_length_semantics);
61
+ nchar = rb_hash_aref(param, sym_nchar);
62
+
63
+ sz = NUM2INT(length);
64
+ if (sz < 0) {
65
+ rb_raise(rb_eArgError, "invalid bind length %d", sz);
66
+ }
67
+ if (length_semantics == sym_char) {
68
+ /* character semantics */
69
+ obs->charlen = sz;
70
+ obs->bytelen = sz = sz * oci8_nls_ratio;
71
+ if (oci8_nls_ratio == 1) {
72
+ /* sz must be bigger than charlen to suppress ORA-06502.
73
+ * I don't know the reason...
74
+ */
75
+ sz *= 2;
43
76
  }
44
- StringValue(val);
45
- sz = RSTRING_LEN(val);
46
77
  } else {
47
- sz = NUM2INT(length);
78
+ /* byte semantics */
79
+ obs->bytelen = sz;
80
+ obs->charlen = 0;
48
81
  }
49
- if (sz < 0) {
50
- rb_raise(rb_eArgError, "invalid bind length %d", sz);
82
+ if (RTEST(nchar)) {
83
+ obs->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
84
+ } else {
85
+ obs->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
86
+ }
87
+ if (sz == 0) {
88
+ sz = 1; /* to avoid ORA-01459. */
51
89
  }
52
90
  sz += sizeof(sb4);
53
91
  obind->value_sz = sz;
54
92
  obind->alloc_sz = (sz + (sizeof(sb4) - 1)) & ~(sizeof(sb4) - 1);
55
93
  }
56
94
 
57
- static const oci8_bind_class_t bind_char_class = {
58
- {
59
- NULL,
60
- oci8_bind_free,
61
- sizeof(oci8_bind_t)
62
- },
63
- bind_string_get,
64
- bind_string_set,
65
- bind_string_init,
66
- NULL,
67
- NULL,
68
- NULL,
69
- NULL,
70
- SQLT_LVC
71
- };
95
+ static void bind_string_post_bind_hook(oci8_bind_t *obind)
96
+ {
97
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
72
98
 
73
- static const oci8_bind_class_t bind_nchar_class = {
99
+ if (obs->charlen != 0) {
100
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&obs->charlen, 0, OCI_ATTR_MAXCHAR_SIZE, oci8_errhp),
101
+ &obind->base);
102
+ }
103
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&obs->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
104
+ &obind->base);
105
+ }
106
+
107
+ static const oci8_bind_vtable_t bind_string_vtable = {
74
108
  {
75
109
  NULL,
76
110
  oci8_bind_free,
77
- sizeof(oci8_bind_t)
111
+ sizeof(oci8_bind_string_t)
78
112
  },
79
113
  bind_string_get,
80
114
  bind_string_set,
81
115
  bind_string_init,
82
116
  NULL,
83
117
  NULL,
84
- NULL,
85
- NULL,
86
118
  SQLT_LVC,
87
- SQLCS_NCHAR,
119
+ bind_string_post_bind_hook,
88
120
  };
89
121
 
90
122
  /*
@@ -98,225 +130,63 @@ static VALUE bind_raw_get(oci8_bind_t *obind, void *data, void *null_struct)
98
130
 
99
131
  static void bind_raw_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
100
132
  {
133
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
101
134
  oci8_vstr_t *vstr = (oci8_vstr_t *)data;
102
135
 
103
136
  StringValue(val);
104
- if (RSTRING_LEN(val) > obind->value_sz - sizeof(vstr->size)) {
105
- rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obind->value_sz - (sb4)sizeof(vstr->size));
137
+ if (RSTRING_LEN(val) > obs->bytelen) {
138
+ rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
106
139
  }
107
140
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
108
141
  vstr->size = RSTRING_LEN(val);
109
142
  }
110
143
 
111
- static const oci8_bind_class_t bind_raw_class = {
144
+ static const oci8_bind_vtable_t bind_raw_vtable = {
112
145
  {
113
146
  NULL,
114
147
  oci8_bind_free,
115
- sizeof(oci8_bind_t)
148
+ sizeof(oci8_bind_string_t)
116
149
  },
117
150
  bind_raw_get,
118
151
  bind_raw_set,
119
152
  bind_string_init,
120
153
  NULL,
121
154
  NULL,
122
- NULL,
123
- NULL,
124
155
  SQLT_LVB
125
156
  };
126
157
 
127
- #ifdef USE_DYNAMIC_FETCH /* don't use DYNAMIC_FETCH. It doesn't work well... */
128
158
  /*
129
- * bind_long
159
+ * bind_binary_double
130
160
  */
131
- typedef struct {
132
- VALUE obj;
133
- ub4 alen;
134
- char buf[1];
135
- } bind_long_t;
136
- #define bind_long_offset ((size_t)((bind_long_t*)0)->buf)
137
-
138
- static void bind_long_mark(oci8_base_t *base)
139
- {
140
- oci8_bind_t *obind = (oci8_bind_t*)base;
141
- ub4 idx = 0;
142
-
143
- if (obind->valuep == NULL)
144
- return;
145
- do {
146
- bind_long_t *bl = (bind_long_t *)((char*)obind->valuep + obind->alloc_sz * idx);
147
- rb_gc_mark(bl->obj);
148
- } while (++idx < obind->maxar_sz);
149
- }
150
-
151
- static VALUE bind_long_get(oci8_bind_t *obind, void *data, void *null_struct)
152
- {
153
- bind_long_t *bl = (bind_long_t *)data;
154
- return RTEST(bl->obj) ? rb_str_dup(bl->obj) : Qnil;
155
- }
156
-
157
- static void bind_long_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
158
- {
159
- bind_long_t *bl = (bind_long_t *)data;
160
- bl->obj = rb_str_dup(val);
161
- }
162
-
163
- static void bind_long_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
164
- {
165
- sb4 sz = 0;
166
-
167
- if (!NIL_P(length)) {
168
- sz = NUM2INT(length);
169
- }
170
- if (sz < 4000) {
171
- sz = 4000;
172
- }
173
- sz += bind_long_offset;
174
- obind->value_sz = INT_MAX;
175
- obind->alloc_sz = (sz + (sizeof(VALUE) - 1)) & ~(sizeof(VALUE) - 1);
176
- }
177
-
178
- static void bind_long_init_elem(oci8_bind_t *obind, VALUE svc)
179
- {
180
- ub4 idx = 0;
181
-
182
- do {
183
- bind_long_t *bl = (bind_long_t *)((char*)obind->valuep + obind->alloc_sz * idx);
184
- bl->obj = Qnil;
185
- } while (++idx < obind->maxar_sz);
186
- }
187
-
188
- static ub1 bind_long_in(oci8_bind_t *obind, ub4 idx, ub1 piece, void **valuepp, ub4 **alenpp, void **indpp)
189
- {
190
- bind_long_t *bl = (bind_long_t *)((char*)obind->valuep + obind->alloc_sz * idx);
191
-
192
- *alenpp = &bl->alen;
193
- *indpp = &obind->u.inds[idx];
194
- if (NIL_P(bl->obj)) {
195
- *valuepp = NULL;
196
- bl->alen = 0;
197
- obind->u.inds[idx] = -1;
198
- } else {
199
- StringValue(bl->obj);
200
- *valuepp = RSTRING_PTR(bl->obj);
201
- bl->alen = RSTRING_LEN(bl->obj);
202
- obind->u.inds[idx] = 0;
203
- }
204
- return OCI_ONE_PIECE;
205
- }
206
-
207
- static void bind_long_out(oci8_bind_t *obind, ub4 idx, ub1 piece, void **valuepp, ub4 **alenpp, void **indpp)
208
- {
209
- bind_long_t *bl = (bind_long_t *)((char*)obind->valuep + obind->alloc_sz * idx);
210
-
211
- switch (piece) {
212
- case OCI_NEXT_PIECE:
213
- case OCI_LAST_PIECE:
214
- if (bl->alen > 0) {
215
- if (!RTEST(bl->obj)) {
216
- bl->obj = rb_str_buf_new(bl->alen);
217
- }
218
- rb_str_buf_cat(bl->obj, bl->buf, bl->alen);
219
- }
220
- break;
221
- default:
222
- /* OCI_FIRST_PIECE is passed at the first call according to manuals.
223
- * But OCI_ONE_PIECE is passed on Oracle 8 and 8i on Windows...
224
- */
225
- bl->obj = Qnil;
226
- }
227
- *valuepp = bl->buf;
228
- *alenpp = &bl->alen;
229
- *indpp = &obind->u.inds[idx];
230
- bl->alen = obind->alloc_sz - bind_long_offset;
231
- obind->u.inds[idx] = 0;
232
- }
233
-
234
- static const oci8_bind_class_t bind_long_class = {
235
- {
236
- bind_long_mark,
237
- oci8_bind_free,
238
- sizeof(oci8_bind_t)
239
- },
240
- bind_long_get,
241
- bind_long_set,
242
- bind_long_init,
243
- bind_long_init_elem,
244
- bind_long_in,
245
- bind_long_out,
246
- NULL,
247
- SQLT_CHR
248
- };
249
-
250
- /*
251
- * bind_long_raw
252
- */
253
- static const oci8_bind_class_t bind_long_raw_class = {
254
- {
255
- bind_long_mark,
256
- oci8_bind_free,
257
- sizeof(oci8_bind_t)
258
- },
259
- bind_long_get,
260
- bind_long_set,
261
- bind_long_init,
262
- bind_long_init_elem,
263
- bind_long_in,
264
- bind_long_out,
265
- NULL,
266
- SQLT_BIN
267
- };
268
- #endif /* USE_DYNAMIC_FETCH */
269
-
270
- /*
271
- * bind_float
272
- */
273
- static VALUE bind_float_get(oci8_bind_t *obind, void *data, void *null_struct)
161
+ static VALUE bind_binary_double_get(oci8_bind_t *obind, void *data, void *null_struct)
274
162
  {
275
163
  return rb_float_new(*(double*)data);
276
164
  }
277
165
 
278
- static void bind_float_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
166
+ static void bind_binary_double_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
279
167
  {
280
168
  /* val is converted to Float if it isn't Float. */
281
169
  *(double*)data = RFLOAT_VALUE(rb_Float(val));
282
170
  }
283
171
 
284
- static void bind_float_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
172
+ static void bind_binary_double_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
285
173
  {
286
174
  obind->value_sz = sizeof(double);
287
175
  obind->alloc_sz = sizeof(double);
288
176
  }
289
177
 
290
- static const oci8_bind_class_t bind_float_class = {
291
- {
292
- NULL,
293
- oci8_bind_free,
294
- sizeof(oci8_bind_t)
295
- },
296
- bind_float_get,
297
- bind_float_set,
298
- bind_float_init,
299
- NULL,
300
- NULL,
301
- NULL,
302
- NULL,
303
- SQLT_FLT
304
- };
305
-
306
178
  #ifndef SQLT_BDOUBLE
307
179
  #define SQLT_BDOUBLE 22
308
180
  #endif
309
- static const oci8_bind_class_t bind_binary_double_class = {
181
+ static const oci8_bind_vtable_t bind_binary_double_vtable = {
310
182
  {
311
183
  NULL,
312
184
  oci8_bind_free,
313
185
  sizeof(oci8_bind_t)
314
186
  },
315
- bind_float_get,
316
- bind_float_set,
317
- bind_float_init,
318
- NULL,
319
- NULL,
187
+ bind_binary_double_get,
188
+ bind_binary_double_set,
189
+ bind_binary_double_init,
320
190
  NULL,
321
191
  NULL,
322
192
  SQLT_BDOUBLE
@@ -325,7 +195,7 @@ static const oci8_bind_class_t bind_binary_double_class = {
325
195
  static VALUE oci8_bind_get(VALUE self)
326
196
  {
327
197
  oci8_bind_t *obind = DATA_PTR(self);
328
- const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
198
+ const oci8_bind_vtable_t *vptr = (const oci8_bind_vtable_t *)obind->base.vptr;
329
199
  ub4 idx = obind->curar_idx;
330
200
  void **null_structp = NULL;
331
201
 
@@ -333,7 +203,7 @@ static VALUE oci8_bind_get(VALUE self)
333
203
  if (obind->u.inds[idx] != 0)
334
204
  return Qnil;
335
205
  }
336
- return obc->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
206
+ return vptr->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
337
207
  }
338
208
 
339
209
  VALUE oci8_bind_get_data(VALUE self)
@@ -358,7 +228,7 @@ VALUE oci8_bind_get_data(VALUE self)
358
228
  static VALUE oci8_bind_set(VALUE self, VALUE val)
359
229
  {
360
230
  oci8_bind_t *obind = DATA_PTR(self);
361
- const oci8_bind_class_t *obc = (const oci8_bind_class_t *)obind->base.klass;
231
+ const oci8_bind_vtable_t *vptr = (const oci8_bind_vtable_t *)obind->base.vptr;
362
232
  ub4 idx = obind->curar_idx;
363
233
 
364
234
  if (NIL_P(val)) {
@@ -377,7 +247,7 @@ static VALUE oci8_bind_set(VALUE self, VALUE val)
377
247
  null_structp = &obind->u.null_structs[idx];
378
248
  *(OCIInd*)obind->u.null_structs[idx] = 0;
379
249
  }
380
- obc->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val);
250
+ vptr->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val);
381
251
  }
382
252
  return self;
383
253
  }
@@ -409,7 +279,7 @@ void oci8_bind_set_data(VALUE self, VALUE val)
409
279
  static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
410
280
  {
411
281
  oci8_bind_t *obind = DATA_PTR(self);
412
- const oci8_bind_class_t *bind_class = (const oci8_bind_class_t *)obind->base.klass;
282
+ const oci8_bind_vtable_t *bind_class = (const oci8_bind_vtable_t *)obind->base.vptr;
413
283
  ub4 cnt = 1;
414
284
 
415
285
  obind->tdo = Qnil;
@@ -471,22 +341,20 @@ void Init_oci8_bind(VALUE klass)
471
341
  {
472
342
  cOCI8BindTypeBase = klass;
473
343
  id_bind_type = rb_intern("bind_type");
344
+ sym_length = ID2SYM(rb_intern("length"));
345
+ sym_length_semantics = ID2SYM(rb_intern("length_semantics"));
346
+ sym_char = ID2SYM(rb_intern("char"));
347
+ sym_nchar = ID2SYM(rb_intern("nchar"));
474
348
 
475
349
  rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
476
350
  rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
477
351
  rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
478
352
 
479
353
  /* register primitive data types. */
480
- oci8_define_bind_class("CHAR", &bind_char_class);
481
- oci8_define_bind_class("NCHAR", &bind_nchar_class);
482
- oci8_define_bind_class("RAW", &bind_raw_class);
483
- #ifdef USE_DYNAMIC_FETCH
484
- oci8_define_bind_class("Long", &bind_long_class);
485
- oci8_define_bind_class("LongRaw", &bind_long_raw_class);
486
- #endif /* USE_DYNAMIC_FETCH */
487
- oci8_define_bind_class("Float", &bind_float_class);
354
+ oci8_define_bind_class("String", &bind_string_vtable);
355
+ oci8_define_bind_class("RAW", &bind_raw_vtable);
488
356
  if (oracle_client_version >= ORAVER_10_1) {
489
- oci8_define_bind_class("BinaryDouble", &bind_binary_double_class);
357
+ oci8_define_bind_class("BinaryDouble", &bind_binary_double_vtable);
490
358
  }
491
359
  }
492
360