ruby-staci 2.2.9

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 (115) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +14 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +3826 -0
  6. data/Makefile +92 -0
  7. data/NEWS +1194 -0
  8. data/README.md +66 -0
  9. data/dist-files +113 -0
  10. data/docs/bind-array-to-in_cond.md +38 -0
  11. data/docs/conflicts-local-connections-and-processes.md +98 -0
  12. data/docs/hanging-after-inactivity.md +63 -0
  13. data/docs/install-binary-package.md +44 -0
  14. data/docs/install-full-client.md +111 -0
  15. data/docs/install-instant-client.md +194 -0
  16. data/docs/install-on-osx.md +133 -0
  17. data/docs/ldap-auth-and-function-interposition.md +123 -0
  18. data/docs/number-type-mapping.md +79 -0
  19. data/docs/osx-install-dev-tools.png +0 -0
  20. data/docs/platform-specific-issues.md +164 -0
  21. data/docs/report-installation-issue.md +50 -0
  22. data/docs/timeout-parameters.md +94 -0
  23. data/ext/oci8/.document +18 -0
  24. data/ext/oci8/MANIFEST +18 -0
  25. data/ext/oci8/apiwrap.c.tmpl +178 -0
  26. data/ext/oci8/apiwrap.h.tmpl +61 -0
  27. data/ext/oci8/apiwrap.rb +96 -0
  28. data/ext/oci8/apiwrap.yml +1322 -0
  29. data/ext/oci8/attr.c +57 -0
  30. data/ext/oci8/bind.c +838 -0
  31. data/ext/oci8/connection_pool.c +216 -0
  32. data/ext/oci8/encoding.c +196 -0
  33. data/ext/oci8/env.c +139 -0
  34. data/ext/oci8/error.c +385 -0
  35. data/ext/oci8/extconf.rb +219 -0
  36. data/ext/oci8/hook_funcs.c +407 -0
  37. data/ext/oci8/lob.c +1278 -0
  38. data/ext/oci8/metadata.c +279 -0
  39. data/ext/oci8/object.c +919 -0
  40. data/ext/oci8/oci8.c +1058 -0
  41. data/ext/oci8/oci8.h +556 -0
  42. data/ext/oci8/oci8lib.c +704 -0
  43. data/ext/oci8/ocidatetime.c +506 -0
  44. data/ext/oci8/ocihandle.c +852 -0
  45. data/ext/oci8/ocinumber.c +1922 -0
  46. data/ext/oci8/oraconf.rb +1145 -0
  47. data/ext/oci8/oradate.c +670 -0
  48. data/ext/oci8/oranumber_util.c +352 -0
  49. data/ext/oci8/oranumber_util.h +24 -0
  50. data/ext/oci8/plthook.h +66 -0
  51. data/ext/oci8/plthook_elf.c +702 -0
  52. data/ext/oci8/plthook_osx.c +505 -0
  53. data/ext/oci8/plthook_win32.c +391 -0
  54. data/ext/oci8/post-config.rb +5 -0
  55. data/ext/oci8/stmt.c +448 -0
  56. data/ext/oci8/thread_util.c +81 -0
  57. data/ext/oci8/thread_util.h +18 -0
  58. data/ext/oci8/util.c +71 -0
  59. data/ext/oci8/win32.c +117 -0
  60. data/lib/.document +1 -0
  61. data/lib/dbd/STACI.rb +591 -0
  62. data/lib/oci8/.document +8 -0
  63. data/lib/oci8/bindtype.rb +333 -0
  64. data/lib/oci8/check_load_error.rb +146 -0
  65. data/lib/oci8/compat.rb +117 -0
  66. data/lib/oci8/connection_pool.rb +179 -0
  67. data/lib/oci8/cursor.rb +605 -0
  68. data/lib/oci8/datetime.rb +605 -0
  69. data/lib/oci8/encoding-init.rb +45 -0
  70. data/lib/oci8/encoding.yml +537 -0
  71. data/lib/oci8/metadata.rb +2148 -0
  72. data/lib/oci8/object.rb +641 -0
  73. data/lib/oci8/oci8.rb +756 -0
  74. data/lib/oci8/ocihandle.rb +591 -0
  75. data/lib/oci8/oracle_version.rb +153 -0
  76. data/lib/oci8/properties.rb +196 -0
  77. data/lib/oci8/version.rb +3 -0
  78. data/lib/ruby-staci.rb +1 -0
  79. data/lib/staci.rb +190 -0
  80. data/metaconfig +142 -0
  81. data/pre-distclean.rb +7 -0
  82. data/ruby-aci.gemspec +83 -0
  83. data/setup.rb +1342 -0
  84. data/test/README.md +37 -0
  85. data/test/config.rb +201 -0
  86. data/test/setup_test_object.sql +199 -0
  87. data/test/setup_test_package.sql +59 -0
  88. data/test/test_all.rb +56 -0
  89. data/test/test_appinfo.rb +62 -0
  90. data/test/test_array_dml.rb +333 -0
  91. data/test/test_bind_array.rb +70 -0
  92. data/test/test_bind_boolean.rb +99 -0
  93. data/test/test_bind_integer.rb +47 -0
  94. data/test/test_bind_raw.rb +45 -0
  95. data/test/test_bind_string.rb +105 -0
  96. data/test/test_bind_time.rb +177 -0
  97. data/test/test_break.rb +124 -0
  98. data/test/test_clob.rb +86 -0
  99. data/test/test_connection_pool.rb +124 -0
  100. data/test/test_connstr.rb +220 -0
  101. data/test/test_datetime.rb +585 -0
  102. data/test/test_dbi.rb +365 -0
  103. data/test/test_dbi_clob.rb +53 -0
  104. data/test/test_encoding.rb +103 -0
  105. data/test/test_error.rb +87 -0
  106. data/test/test_metadata.rb +2674 -0
  107. data/test/test_object.rb +546 -0
  108. data/test/test_oci8.rb +624 -0
  109. data/test/test_oracle_version.rb +68 -0
  110. data/test/test_oradate.rb +255 -0
  111. data/test/test_oranumber.rb +786 -0
  112. data/test/test_package_type.rb +981 -0
  113. data/test/test_properties.rb +17 -0
  114. data/test/test_rowid.rb +32 -0
  115. metadata +158 -0
data/ext/oci8/bind.c ADDED
@@ -0,0 +1,838 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * bind.c
4
+ *
5
+ * Copyright (C) 2002-2014 Kubo Takehiro <kubo@jiubao.org>
6
+ */
7
+ #include "oci8.h"
8
+
9
+ #ifndef OCI_ATTR_MAXCHAR_SIZE
10
+ #define OCI_ATTR_MAXCHAR_SIZE 164
11
+ #endif
12
+
13
+ static ID id_bind_type;
14
+ static ID id_charset_form;
15
+ static VALUE sym_length;
16
+ static VALUE sym_length_semantics;
17
+ static VALUE sym_char;
18
+ static VALUE sym_nchar;
19
+
20
+ static VALUE cOCI8BindTypeBase;
21
+
22
+ typedef struct {
23
+ oci8_bind_t obind;
24
+ sb4 bytelen;
25
+ sb4 charlen;
26
+ ub1 csfrm;
27
+ } oci8_bind_string_t;
28
+
29
+ static ub4 initial_chunk_size = 32 * 1024;
30
+ static ub4 max_chunk_size = 8 * 1024 * 1024;
31
+
32
+ typedef struct chunk {
33
+ struct chunk *next;
34
+ ub4 alloc_len;
35
+ ub4 used_len;
36
+ char buf[1];
37
+ } chunk_t;
38
+
39
+ typedef struct {
40
+ chunk_t *head;
41
+ chunk_t **tail;
42
+ chunk_t **inpos;
43
+ } chunk_buf_t;
44
+
45
+ typedef struct {
46
+ oci8_bind_t obind;
47
+ ub1 csfrm;
48
+ } oci8_bind_long_t;
49
+
50
+ #define IS_BIND_LONG(obind) (((oci8_bind_data_type_t*)obind->base.data_type)->dty == SQLT_CHR)
51
+
52
+ const oci8_handle_data_type_t oci8_bind_data_type = {
53
+ {
54
+ "STACI::BindType::Base",
55
+ {
56
+ NULL,
57
+ oci8_handle_cleanup,
58
+ oci8_handle_size,
59
+ },
60
+ &oci8_handle_data_type.rb_data_type, NULL,
61
+ #ifdef RUBY_TYPED_WB_PROTECTED
62
+ RUBY_TYPED_WB_PROTECTED,
63
+ #endif
64
+ },
65
+ NULL,
66
+ 0,
67
+ };
68
+
69
+ /*
70
+ * bind_string
71
+ */
72
+ static VALUE bind_string_get(oci8_bind_t *obind, void *data, void *null_struct)
73
+ {
74
+ oci8_vstr_t *vstr = (oci8_vstr_t *)data;
75
+ return rb_external_str_new_with_enc(vstr->buf, vstr->size, oci8_encoding);
76
+ }
77
+
78
+ static void bind_string_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
79
+ {
80
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
81
+ oci8_vstr_t *vstr = (oci8_vstr_t *)data;
82
+
83
+ OCI8StringValue(val);
84
+ if (RSTRING_LEN(val) > obs->bytelen) {
85
+ rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
86
+ }
87
+ memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
88
+ vstr->size = RSTRING_LEN(val);
89
+ }
90
+
91
+ static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
92
+ {
93
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
94
+ VALUE length;
95
+ VALUE length_semantics;
96
+ VALUE nchar;
97
+ sb4 sz;
98
+
99
+ Check_Type(param, T_HASH);
100
+ length = rb_hash_aref(param, sym_length);
101
+ length_semantics = rb_hash_aref(param, sym_length_semantics);
102
+ nchar = rb_hash_aref(param, sym_nchar);
103
+
104
+ sz = NUM2INT(length);
105
+ if (sz < 0) {
106
+ rb_raise(rb_eArgError, "invalid bind length %d", sz);
107
+ }
108
+ if (length_semantics == sym_char) {
109
+ /* character semantics */
110
+ obs->charlen = sz;
111
+ obs->bytelen = sz = sz * oci8_nls_ratio;
112
+ if (oci8_nls_ratio == 1) {
113
+ /* sz must be bigger than charlen to suppress ORA-06502.
114
+ * I don't know the reason...
115
+ */
116
+ sz *= 2;
117
+ }
118
+ } else {
119
+ /* byte semantics */
120
+ obs->bytelen = sz;
121
+ obs->charlen = 0;
122
+ }
123
+ if (RTEST(nchar)) {
124
+ obs->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
125
+ } else {
126
+ obs->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
127
+ }
128
+ if (sz == 0) {
129
+ sz = 1; /* to avoid ORA-01459. */
130
+ }
131
+ sz += sizeof(sb4);
132
+ obind->value_sz = sz;
133
+ obind->alloc_sz = (sz + (sizeof(sb4) - 1)) & ~(sizeof(sb4) - 1);
134
+ }
135
+
136
+ static void bind_string_post_bind_hook(oci8_bind_t *obind)
137
+ {
138
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
139
+
140
+ if (obs->charlen != 0) {
141
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&obs->charlen, 0, OCI_ATTR_MAXCHAR_SIZE, oci8_errhp),
142
+ &obind->base);
143
+ }
144
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&obs->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
145
+ &obind->base);
146
+ }
147
+
148
+ static const oci8_bind_data_type_t bind_string_data_type = {
149
+ {
150
+ {
151
+ "STACI::BindType::String",
152
+ {
153
+ NULL,
154
+ oci8_handle_cleanup,
155
+ oci8_handle_size,
156
+ },
157
+ &oci8_bind_data_type.rb_data_type, NULL,
158
+ #ifdef RUBY_TYPED_WB_PROTECTED
159
+ RUBY_TYPED_WB_PROTECTED,
160
+ #endif
161
+ },
162
+ oci8_bind_free,
163
+ sizeof(oci8_bind_string_t)
164
+ },
165
+ bind_string_get,
166
+ bind_string_set,
167
+ bind_string_init,
168
+ NULL,
169
+ NULL,
170
+ SQLT_LVC,
171
+ bind_string_post_bind_hook,
172
+ };
173
+
174
+ static VALUE bind_string_alloc(VALUE klass)
175
+ {
176
+ return oci8_allocate_typeddata(klass, &bind_string_data_type.base);
177
+ }
178
+
179
+ /*
180
+ * bind_raw
181
+ */
182
+ static VALUE bind_raw_get(oci8_bind_t *obind, void *data, void *null_struct)
183
+ {
184
+ oci8_vstr_t *vstr = (oci8_vstr_t *)data;
185
+ return rb_str_new(vstr->buf, vstr->size);
186
+ }
187
+
188
+ static void bind_raw_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
189
+ {
190
+ oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
191
+ oci8_vstr_t *vstr = (oci8_vstr_t *)data;
192
+
193
+ StringValue(val);
194
+ if (RSTRING_LEN(val) > obs->bytelen) {
195
+ rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
196
+ }
197
+ memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
198
+ vstr->size = RSTRING_LEN(val);
199
+ }
200
+
201
+ static const oci8_bind_data_type_t bind_raw_data_type = {
202
+ {
203
+ {
204
+ "STACI::BindType::RAW",
205
+ {
206
+ NULL,
207
+ oci8_handle_cleanup,
208
+ oci8_handle_size,
209
+ },
210
+ &oci8_bind_data_type.rb_data_type, NULL,
211
+ #ifdef RUBY_TYPED_WB_PROTECTED
212
+ RUBY_TYPED_WB_PROTECTED,
213
+ #endif
214
+ },
215
+ oci8_bind_free,
216
+ sizeof(oci8_bind_string_t)
217
+ },
218
+ bind_raw_get,
219
+ bind_raw_set,
220
+ bind_string_init,
221
+ NULL,
222
+ NULL,
223
+ SQLT_LVB
224
+ };
225
+
226
+ static VALUE bind_raw_alloc(VALUE klass)
227
+ {
228
+ return oci8_allocate_typeddata(klass, &bind_raw_data_type.base);
229
+ }
230
+
231
+ /*
232
+ * bind_binary_double
233
+ */
234
+ static VALUE bind_binary_double_get(oci8_bind_t *obind, void *data, void *null_struct)
235
+ {
236
+ return rb_float_new(*(double*)data);
237
+ }
238
+
239
+ static void bind_binary_double_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
240
+ {
241
+ /* val is converted to Float if it isn't Float. */
242
+ *(double*)data = RFLOAT_VALUE(rb_Float(val));
243
+ }
244
+
245
+ static void bind_binary_double_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
246
+ {
247
+ obind->value_sz = sizeof(double);
248
+ obind->alloc_sz = sizeof(double);
249
+ }
250
+
251
+ static const oci8_bind_data_type_t bind_binary_double_data_type = {
252
+ {
253
+ {
254
+ "STACI::BindType::BinaryDouble",
255
+ {
256
+ NULL,
257
+ oci8_handle_cleanup,
258
+ oci8_handle_size,
259
+ },
260
+ &oci8_bind_data_type.rb_data_type, NULL,
261
+ #ifdef RUBY_TYPED_WB_PROTECTED
262
+ RUBY_TYPED_WB_PROTECTED,
263
+ #endif
264
+ },
265
+ oci8_bind_free,
266
+ sizeof(oci8_bind_t)
267
+ },
268
+ bind_binary_double_get,
269
+ bind_binary_double_set,
270
+ bind_binary_double_init,
271
+ NULL,
272
+ NULL,
273
+ SQLT_BDOUBLE
274
+ };
275
+
276
+ static VALUE bind_binary_double_alloc(VALUE klass)
277
+ {
278
+ return oci8_allocate_typeddata(klass, &bind_binary_double_data_type.base);
279
+ }
280
+
281
+ /*
282
+ * bind_boolean
283
+ */
284
+ static VALUE bind_boolean_get(oci8_bind_t *obind, void *data, void *null_struct)
285
+ {
286
+ return *(int*)data ? Qtrue : Qfalse;
287
+ }
288
+
289
+ static void bind_boolean_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
290
+ {
291
+ *(int*)data = RTEST(val) ? -1 : 0;
292
+ }
293
+
294
+ static void bind_boolean_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE length)
295
+ {
296
+ obind->value_sz = sizeof(int);
297
+ obind->alloc_sz = sizeof(int);
298
+ }
299
+
300
+ #ifndef SQLT_BOL
301
+ #define SQLT_BOL 252
302
+ #endif
303
+ static const oci8_bind_data_type_t bind_boolean_data_type = {
304
+ {
305
+ {
306
+ "STACI::BindType::Boolean",
307
+ {
308
+ NULL,
309
+ oci8_handle_cleanup,
310
+ oci8_handle_size,
311
+ },
312
+ &oci8_bind_data_type.rb_data_type, NULL,
313
+ #ifdef RUBY_TYPED_WB_PROTECTED
314
+ RUBY_TYPED_WB_PROTECTED,
315
+ #endif
316
+ },
317
+ oci8_bind_free,
318
+ sizeof(oci8_bind_t)
319
+ },
320
+ bind_boolean_get,
321
+ bind_boolean_set,
322
+ bind_boolean_init,
323
+ NULL,
324
+ NULL,
325
+ SQLT_BOL,
326
+ };
327
+
328
+ static VALUE bind_boolean_alloc(VALUE klass)
329
+ {
330
+ return oci8_allocate_typeddata(klass, &bind_boolean_data_type.base);
331
+ }
332
+
333
+ /*
334
+ * bind_long
335
+ */
336
+ static chunk_t *next_chunk(chunk_buf_t *cb)
337
+ {
338
+ chunk_t *chunk;
339
+
340
+ if (*cb->tail != NULL) {
341
+ chunk = *cb->tail;
342
+ } else {
343
+ ub4 alloc_len;
344
+ if (cb->head == NULL) {
345
+ alloc_len = initial_chunk_size;
346
+ } else {
347
+ alloc_len = ((chunk_t*)((size_t)cb->tail - offsetof(chunk_t, next)))->alloc_len * 2;
348
+ if (alloc_len > max_chunk_size) {
349
+ alloc_len = max_chunk_size;
350
+ }
351
+ }
352
+ chunk = xmalloc(offsetof(chunk_t, buf) + alloc_len);
353
+ chunk->next = NULL;
354
+ chunk->alloc_len = alloc_len;
355
+ *cb->tail = chunk;
356
+ }
357
+ cb->tail = &chunk->next;
358
+ return chunk;
359
+ }
360
+
361
+ static sb4 define_callback(void *octxp, OCIDefine *defnp, ub4 iter, void **bufpp, ub4 **alenp, ub1 *piecep, void **indp, ub2 **rcodep)
362
+ {
363
+ oci8_bind_t *obind = (oci8_bind_t *)octxp;
364
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
365
+ chunk_t *chunk;
366
+
367
+ if (*piecep == OCI_FIRST_PIECE) {
368
+ cb->tail = &cb->head;
369
+ }
370
+ chunk = next_chunk(cb);
371
+ chunk->used_len = chunk->alloc_len;
372
+ *bufpp = chunk->buf;
373
+ *alenp = &chunk->used_len;
374
+ *indp = (void*)&obind->u.inds[iter];
375
+ *rcodep = NULL;
376
+ return OCI_CONTINUE;
377
+ }
378
+
379
+ static sb4 in_bind_callback(void *ictxp, OCIBind *bindp, ub4 iter, ub4 index, void **bufpp, ub4 *alenp, ub1 *piecep, void **indp)
380
+ {
381
+ oci8_bind_t *obind = (oci8_bind_t *)ictxp;
382
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
383
+
384
+ if (cb->tail == &cb->head) {
385
+ /* empty string */
386
+ *bufpp = (void *)"";
387
+ *alenp = 0;
388
+ *piecep = OCI_ONE_PIECE;
389
+ } else {
390
+ chunk_t *chunk = *cb->inpos;
391
+ *bufpp = chunk->buf;
392
+ *alenp = chunk->used_len;
393
+ if (cb->tail == &cb->head->next) {
394
+ *piecep = OCI_ONE_PIECE;
395
+ } else if (cb->inpos == &cb->head) {
396
+ *piecep = OCI_FIRST_PIECE;
397
+ cb->inpos = &chunk->next;
398
+ } else if (&chunk->next != cb->tail) {
399
+ *piecep = OCI_NEXT_PIECE;
400
+ cb->inpos = &chunk->next;
401
+ } else {
402
+ *piecep = OCI_LAST_PIECE;
403
+ cb->inpos = &cb->head;
404
+ }
405
+ }
406
+ *indp = (void*)&obind->u.inds[iter];
407
+ return OCI_CONTINUE;
408
+ }
409
+
410
+ static sb4 out_bind_callback(void *octxp, OCIBind *bindp, ub4 iter, ub4 index, void **bufpp, ub4 **alenp, ub1 *piecep, void **indp, ub2 **rcodep)
411
+ {
412
+ oci8_bind_t *obind = (oci8_bind_t *)octxp;
413
+ chunk_buf_t *cb = ((chunk_buf_t*)obind->valuep) + iter;
414
+ chunk_t *chunk;
415
+
416
+ if (*piecep == OCI_ONE_PIECE) {
417
+ *piecep = OCI_FIRST_PIECE;
418
+ cb->tail = &cb->head;
419
+ }
420
+ chunk = next_chunk(cb);
421
+ chunk->used_len = chunk->alloc_len;
422
+ *bufpp = chunk->buf;
423
+ *alenp = &chunk->used_len;
424
+ *indp = (void*)&obind->u.inds[iter];
425
+ *rcodep = NULL;
426
+ return OCI_CONTINUE;
427
+ }
428
+
429
+ static void bind_long_free(oci8_base_t *base)
430
+ {
431
+ oci8_bind_t *obind = (oci8_bind_t *)base;
432
+ chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
433
+
434
+ if (cb != NULL) {
435
+ ub4 idx = 0;
436
+ do {
437
+ chunk_t *chunk, *chunk_next;
438
+ for (chunk = cb[idx].head; chunk != NULL; chunk = chunk_next) {
439
+ chunk_next = chunk->next;
440
+ xfree(chunk);
441
+ }
442
+ } while (++idx < obind->maxar_sz);
443
+ }
444
+ oci8_bind_free(base);
445
+ }
446
+
447
+ static VALUE bind_long_get(oci8_bind_t *obind, void *data, void *null_struct)
448
+ {
449
+ chunk_buf_t *cb = (chunk_buf_t *)data;
450
+ chunk_t *chunk;
451
+ long len = 0;
452
+ VALUE str;
453
+ char *buf;
454
+
455
+ for (chunk = cb->head; chunk != *cb->tail; chunk = chunk->next) {
456
+ len += chunk->used_len;
457
+ }
458
+ str = rb_str_buf_new(len);
459
+ buf = RSTRING_PTR(str);
460
+ for (chunk = cb->head; chunk != *cb->tail; chunk = chunk->next) {
461
+ memcpy(buf, chunk->buf, chunk->used_len);
462
+ buf += chunk->used_len;
463
+ }
464
+ rb_str_set_len(str, len);
465
+ if (IS_BIND_LONG(obind)) {
466
+ rb_encoding *enc = rb_default_internal_encoding();
467
+
468
+ rb_enc_associate(str, oci8_encoding);
469
+ if (enc != NULL) {
470
+ str = rb_str_conv_enc(str, oci8_encoding, enc);
471
+ }
472
+ }
473
+ OBJ_TAINT(str);
474
+ return str;
475
+ }
476
+
477
+ static void bind_long_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
478
+ {
479
+ chunk_buf_t *cb = (chunk_buf_t *)data;
480
+ ub4 len;
481
+ const char *buf;
482
+
483
+ if (IS_BIND_LONG(obind)) {
484
+ OCI8StringValue(val);
485
+ } else {
486
+ StringValue(val);
487
+ }
488
+ len = (ub4)RSTRING_LEN(val);
489
+ buf = RSTRING_PTR(val);
490
+ cb->tail = &cb->head;
491
+ while (1) {
492
+ chunk_t *chunk = next_chunk(cb);
493
+ if (len <= chunk->alloc_len) {
494
+ memcpy(chunk->buf, buf, len);
495
+ chunk->used_len = len;
496
+ break;
497
+ }
498
+ memcpy(chunk->buf, buf, chunk->alloc_len);
499
+ chunk->used_len = chunk->alloc_len;
500
+ len -= chunk->alloc_len;
501
+ buf += chunk->alloc_len;
502
+ }
503
+ }
504
+
505
+ static void bind_long_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
506
+ {
507
+ if (IS_BIND_LONG(obind)) {
508
+ oci8_bind_long_t *obl = (oci8_bind_long_t *)obind;
509
+ VALUE nchar;
510
+
511
+ if (rb_respond_to(param, id_charset_form)) {
512
+ VALUE csfrm = rb_funcall(param, id_charset_form, 0);
513
+ nchar = (csfrm == sym_nchar) ? Qtrue : Qfalse;
514
+ } else {
515
+ Check_Type(param, T_HASH);
516
+ nchar = rb_hash_aref(param, sym_nchar);
517
+ }
518
+
519
+ if (RTEST(nchar)) {
520
+ obl->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
521
+ } else {
522
+ obl->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
523
+ }
524
+ }
525
+ obind->value_sz = SB4MAXVAL;
526
+ obind->alloc_sz = sizeof(chunk_buf_t);
527
+ }
528
+
529
+ static void bind_long_init_elem(oci8_bind_t *obind, VALUE svc)
530
+ {
531
+ chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
532
+ ub4 idx = 0;
533
+
534
+ do {
535
+ cb[idx].tail = &cb[idx].head;
536
+ cb[idx].inpos = &cb[idx].head;
537
+ } while (++idx < obind->maxar_sz);
538
+ }
539
+
540
+ static void bind_long_post_bind_hook(oci8_bind_t *obind)
541
+ {
542
+ oci8_bind_long_t *ds = (oci8_bind_long_t *)obind;
543
+
544
+ if (IS_BIND_LONG(obind)) {
545
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&ds->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
546
+ &obind->base);
547
+ }
548
+ switch (obind->base.type) {
549
+ case OCI_HTYPE_DEFINE:
550
+ chker2(OCIDefineDynamic(obind->base.hp.dfn, oci8_errhp, obind, define_callback),
551
+ &obind->base);
552
+ break;
553
+ case OCI_HTYPE_BIND:
554
+ chker2(OCIBindDynamic(obind->base.hp.bnd, oci8_errhp, obind, in_bind_callback,
555
+ obind, out_bind_callback),
556
+ &obind->base);
557
+ break;
558
+ }
559
+ }
560
+
561
+ static const oci8_bind_data_type_t bind_long_data_type = {
562
+ {
563
+ {
564
+ "STACI::BindType::Long",
565
+ {
566
+ NULL,
567
+ oci8_handle_cleanup,
568
+ oci8_handle_size,
569
+ },
570
+ &oci8_bind_data_type.rb_data_type, NULL,
571
+ #ifdef RUBY_TYPED_WB_PROTECTED
572
+ RUBY_TYPED_WB_PROTECTED,
573
+ #endif
574
+ },
575
+ bind_long_free,
576
+ sizeof(oci8_bind_long_t)
577
+ },
578
+ bind_long_get,
579
+ bind_long_set,
580
+ bind_long_init,
581
+ bind_long_init_elem,
582
+ NULL,
583
+ SQLT_CHR,
584
+ bind_long_post_bind_hook,
585
+ };
586
+
587
+ static VALUE bind_long_alloc(VALUE klass)
588
+ {
589
+ return oci8_allocate_typeddata(klass, &bind_long_data_type.base);
590
+ }
591
+
592
+ static const oci8_bind_data_type_t bind_long_raw_data_type = {
593
+ {
594
+ {
595
+ "OCI8::BindType::LongRaw",
596
+ {
597
+ NULL,
598
+ oci8_handle_cleanup,
599
+ oci8_handle_size,
600
+ },
601
+ &oci8_bind_data_type.rb_data_type, NULL,
602
+ #ifdef RUBY_TYPED_WB_PROTECTED
603
+ RUBY_TYPED_WB_PROTECTED,
604
+ #endif
605
+ },
606
+ bind_long_free,
607
+ sizeof(oci8_bind_long_t)
608
+ },
609
+ bind_long_get,
610
+ bind_long_set,
611
+ bind_long_init,
612
+ bind_long_init_elem,
613
+ NULL,
614
+ SQLT_BIN,
615
+ bind_long_post_bind_hook,
616
+ };
617
+
618
+ static VALUE bind_long_raw_alloc(VALUE klass)
619
+ {
620
+ return oci8_allocate_typeddata(klass, &bind_long_raw_data_type.base);
621
+ }
622
+
623
+ static VALUE oci8_bind_get(VALUE self)
624
+ {
625
+ oci8_bind_t *obind = TO_BIND(self);
626
+ const oci8_bind_data_type_t *data_type = (const oci8_bind_data_type_t *)obind->base.data_type;
627
+ ub4 idx = obind->curar_idx;
628
+ void **null_structp = NULL;
629
+
630
+ if (NIL_P(obind->tdo)) {
631
+ if (obind->u.inds[idx] != 0)
632
+ return Qnil;
633
+ }
634
+ return data_type->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
635
+ }
636
+
637
+ static VALUE oci8_bind_get_data(int argc, VALUE *argv, VALUE self)
638
+ {
639
+ oci8_bind_t *obind = TO_BIND(self);
640
+ VALUE index;
641
+
642
+ rb_scan_args(argc, argv, "01", &index);
643
+ if (!NIL_P(index)) {
644
+ ub4 idx = NUM2UINT(index);
645
+ if (idx >= obind->maxar_sz) {
646
+ rb_raise(rb_eRuntimeError, "data index is too big. (%u for %u)", idx, obind->maxar_sz);
647
+ }
648
+ obind->curar_idx = idx;
649
+ return rb_funcall(self, oci8_id_get, 0);
650
+ } else if (obind->maxar_sz == 0) {
651
+ obind->curar_idx = 0;
652
+ return rb_funcall(self, oci8_id_get, 0);
653
+ } else {
654
+ volatile VALUE ary = rb_ary_new2(obind->curar_sz);
655
+ ub4 idx;
656
+
657
+ for (idx = 0; idx < obind->curar_sz; idx++) {
658
+ obind->curar_idx = idx;
659
+ rb_ary_store(ary, idx, rb_funcall(self, oci8_id_get, 0));
660
+ }
661
+ return ary;
662
+ }
663
+ }
664
+
665
+ static VALUE oci8_bind_set(VALUE self, VALUE val)
666
+ {
667
+ oci8_bind_t *obind = TO_BIND(self);
668
+ const oci8_bind_data_type_t *data_type = (const oci8_bind_data_type_t *)obind->base.data_type;
669
+ ub4 idx = obind->curar_idx;
670
+
671
+ if (NIL_P(val)) {
672
+ if (NIL_P(obind->tdo)) {
673
+ obind->u.inds[idx] = -1;
674
+ } else {
675
+ *(OCIInd*)obind->u.null_structs[idx] = -1;
676
+ }
677
+ } else {
678
+ void **null_structp = NULL;
679
+
680
+ if (NIL_P(obind->tdo)) {
681
+ null_structp = NULL;
682
+ obind->u.inds[idx] = 0;
683
+ } else {
684
+ null_structp = &obind->u.null_structs[idx];
685
+ *(OCIInd*)obind->u.null_structs[idx] = 0;
686
+ }
687
+ data_type->set(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp, val);
688
+ }
689
+ return self;
690
+ }
691
+
692
+ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
693
+ {
694
+ oci8_bind_t *obind = TO_BIND(self);
695
+
696
+ if (obind->maxar_sz == 0) {
697
+ obind->curar_idx = 0;
698
+ rb_funcall(self, oci8_id_set, 1, val);
699
+ } else {
700
+ ub4 size;
701
+ ub4 idx;
702
+ Check_Type(val, T_ARRAY);
703
+
704
+ size = RARRAY_LEN(val);
705
+ if (size > obind->maxar_sz) {
706
+ rb_raise(rb_eRuntimeError, "over the max array size");
707
+ }
708
+ for (idx = 0; idx < size; idx++) {
709
+ obind->curar_idx = idx;
710
+ rb_funcall(self, oci8_id_set, 1, RARRAY_AREF(val, idx));
711
+ }
712
+ obind->curar_sz = size;
713
+ }
714
+ return self;
715
+ }
716
+
717
+ static VALUE get_initial_chunk_size(VALUE klass)
718
+ {
719
+ return UINT2NUM(initial_chunk_size);
720
+ }
721
+
722
+ static VALUE set_initial_chunk_size(VALUE klass, VALUE arg)
723
+ {
724
+ ub4 size = NUM2UINT(arg);
725
+ if (size == 0) {
726
+ rb_raise(rb_eArgError, "Could not set zero");
727
+ }
728
+ initial_chunk_size = size;
729
+ return arg;
730
+ }
731
+
732
+ static VALUE get_max_chunk_size(VALUE klass)
733
+ {
734
+ return UINT2NUM(max_chunk_size);
735
+ }
736
+
737
+ static VALUE set_max_chunk_size(VALUE klass, VALUE arg)
738
+ {
739
+ ub4 size = NUM2UINT(arg);
740
+ if (size == 0) {
741
+ rb_raise(rb_eArgError, "Could not set zero");
742
+ }
743
+ max_chunk_size = size;
744
+ return arg;
745
+ }
746
+
747
+ static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
748
+ {
749
+ oci8_bind_t *obind = TO_BIND(self);
750
+ const oci8_bind_data_type_t *bind_class = (const oci8_bind_data_type_t *)obind->base.data_type;
751
+ ub4 cnt = 1;
752
+
753
+ obind->tdo = Qnil;
754
+ obind->maxar_sz = NIL_P(max_array_size) ? 0 : NUM2UINT(max_array_size);
755
+ obind->curar_sz = 0;
756
+ if (obind->maxar_sz > 0)
757
+ cnt = obind->maxar_sz;
758
+ bind_class->init(obind, svc, val, length);
759
+ if (obind->alloc_sz > 0) {
760
+ obind->valuep = xmalloc(obind->alloc_sz * cnt);
761
+ memset(obind->valuep, 0, obind->alloc_sz * cnt);
762
+ } else {
763
+ obind->valuep = NULL;
764
+ }
765
+ if (NIL_P(obind->tdo)) {
766
+ obind->u.inds = xmalloc(sizeof(sb2) * cnt);
767
+ memset(obind->u.inds, -1, sizeof(sb2) * cnt);
768
+ } else {
769
+ obind->u.null_structs = xmalloc(sizeof(void *) * cnt);
770
+ memset(obind->u.null_structs, 0, sizeof(void *) * cnt);
771
+ }
772
+ if (bind_class->init_elem != NULL) {
773
+ bind_class->init_elem(obind, svc);
774
+ }
775
+ if (!NIL_P(val)) {
776
+ oci8_bind_set_data(self, val);
777
+ }
778
+ return Qnil;
779
+ }
780
+
781
+ void oci8_bind_free(oci8_base_t *base)
782
+ {
783
+ oci8_bind_t *obind = (oci8_bind_t *)base;
784
+ if (obind->valuep != NULL) {
785
+ xfree(obind->valuep);
786
+ obind->valuep = NULL;
787
+ }
788
+ if (obind->u.inds != NULL) {
789
+ xfree(obind->u.inds);
790
+ obind->u.inds = NULL;
791
+ }
792
+ }
793
+
794
+ void oci8_bind_hp_obj_mark(oci8_base_t *base)
795
+ {
796
+ oci8_bind_t *obind = (oci8_bind_t *)base;
797
+ oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
798
+
799
+ if (oho != NULL) {
800
+ ub4 idx = 0;
801
+
802
+ do {
803
+ rb_gc_mark(oho[idx].obj);
804
+ } while (++idx < obind->maxar_sz);
805
+ }
806
+ }
807
+
808
+ void Init_oci8_bind(VALUE klass)
809
+ {
810
+ cOCI8BindTypeBase = klass;
811
+ id_bind_type = rb_intern("bind_type");
812
+ id_charset_form = rb_intern("charset_form");
813
+ sym_length = ID2SYM(rb_intern("length"));
814
+ sym_length_semantics = ID2SYM(rb_intern("length_semantics"));
815
+ sym_char = ID2SYM(rb_intern("char"));
816
+ sym_nchar = ID2SYM(rb_intern("nchar"));
817
+
818
+ rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
819
+ rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
820
+ rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
821
+ rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, -1);
822
+ rb_define_private_method(cOCI8BindTypeBase, "set_data", oci8_bind_set_data, 1);
823
+
824
+ rb_define_singleton_method(klass, "initial_chunk_size", get_initial_chunk_size, 0);
825
+ rb_define_singleton_method(klass, "initial_chunk_size=", set_initial_chunk_size, 1);
826
+ rb_define_singleton_method(klass, "max_chunk_size", get_max_chunk_size, 0);
827
+ rb_define_singleton_method(klass, "max_chunk_size=", set_max_chunk_size, 1);
828
+
829
+ /* register primitive data types. */
830
+ oci8_define_bind_class("String", &bind_string_data_type, bind_string_alloc);
831
+ oci8_define_bind_class("RAW", &bind_raw_data_type, bind_raw_alloc);
832
+ oci8_define_bind_class("BinaryDouble", &bind_binary_double_data_type, bind_binary_double_alloc);
833
+ if (oracle_client_version >= ORAVER_12_1) {
834
+ oci8_define_bind_class("Boolean", &bind_boolean_data_type, bind_boolean_alloc);
835
+ }
836
+ klass = oci8_define_bind_class("Long", &bind_long_data_type, bind_long_alloc);
837
+ klass = oci8_define_bind_class("LongRaw", &bind_long_data_type, bind_long_raw_alloc);
838
+ }