ruby-oci8 2.2.6.1 → 2.2.10

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.
@@ -1,133 +1,46 @@
1
- # @title Install ruby-oci8 on OS X
1
+ # @title Install ruby-oci8 on macOS
2
2
 
3
- Install ruby-oci8 on OS X
3
+ Install ruby-oci8 on macOS
4
4
  =========================
5
5
 
6
- This page explains the way to install ruby-oci8 os OS X.
6
+ **Note: Ruby-oci8 doesn't run on Apple Silicon because Oracle instant client
7
+ for Apple Silicon has not been released yet.**
7
8
 
8
- Look at {file:docs/install-full-client.md}, {file:docs/install-instant-client.md}
9
- or {file:docs/install-binary-package.md} for other platforms.
10
-
11
- Install C compiler
12
- ------------------
13
-
14
- You need to install the command line developer tools or the Xcode.
15
- (The latter includes the former.)
16
-
17
- Run `"cc --version"` in a terminal to check whether they are installed.
18
-
19
- If the cc version is printed, the tools are installed.
20
-
21
- If the follwoing dialog is displayed, click its Install button to
22
- install the tools.
23
- You have no need to install the Xcode to compile ruby-oci8.
24
- It requires command line tools, not an IDE such as the Xcode.
25
-
26
- ![dialog](osx-install-dev-tools.png)
9
+ Prerequisite
10
+ ------------
27
11
 
28
- If `"Agreeing to the Xcode/iOS license requires admin privileges,
29
- please re-run as root via sudo."` is printed, you need to run
30
- `"sudo cc --version"`, enter your password, look at the license
31
- and type `"agree"`.
12
+ * Command line tools for Xcode or Xcode (by executing `xcode-select --install`) or [Xcode]
32
13
 
33
14
  Install Oracle Instant Client Packages
34
15
  --------------------------------------
35
16
 
36
- ### Download Oracle Instant Client Packages
37
-
38
- Download the following packages from [Oracle Technology Network][]
39
-
40
- * Instant Client Package - Basic (`instantclient-basic-macos.x64-12.1.0.2.0.zip`) or Basic Lite (`instantclient-basiclite-macos.x64-12.1.0.2.0.zip`)
41
- * Instant Client Package - SDK (`instantclient-sdk-macos.x64-12.1.0.2.0.zip`)
42
- * Instant Client Package - SQL*Plus (`instantclient-sqlplus-macos.x64-12.1.0.2.0.zip`) (optionally)
43
-
44
- ### Install Oracle Instant Client Packages via Homebrew
45
-
46
- To install `Oracle Instant Client Basic` via [Homebrew][]
47
-
48
- * Copy downloaded zip files to `/Library/Caches/Homebrew`
49
- (if the environment variable `HOMEBREW_CACHE`
50
- is not set and `$HOME/Library/Caches/Homebrew` doesn't exist.)
51
-
52
- * Run the followining commands:
53
-
54
- brew tap InstantClientTap/instantclient
55
- brew install instantclient-basic
56
- brew install instantclient-sdk
57
- brew install instantclient-sqlplus # (optionally)
58
-
59
- * Set the environment variable `OCI_DIR` while performing the following installation steps
60
- if Homebrew is installed outside `/usr/local`.
61
-
62
- export OCI_DIR=$(brew --prefix)/lib
63
-
64
- To install `Oracle Instant Client Basic Lite` via [Homebrew][]
65
-
66
- * Copy downloaded zip files to `/Library/Caches/Homebrew`
67
- (if the environment variable `HOMEBREW_CACHE`
68
- is not set and `$HOME/Library/Caches/Homebrew` doesn't exist.)
69
-
70
- * Run the followining commands:
71
-
72
- brew tap InstantClientTap/instantclient
73
- brew install instantclient-basiclite
74
- brew install instantclient-sdk
75
- brew install instantclient-sqlplus --with-basiclite # (optionally)
76
-
77
- * Set the environment variable `OCI_DIR` while performing the following installation steps
78
- if Homebrew is installed outside `/usr/local`.
79
-
80
- export OCI_DIR=$(brew --prefix)/lib
81
-
82
- ### Install Oracle Instant Client Manually
83
-
84
- If you don't use [Homebrew][], do the following:
85
-
86
- Unzip the packages as follows:
87
-
88
- mkdir -p /opt/oracle
89
- cd /opt/oracle
90
-
91
- Copy downloaded files to /opt/oracle before running the following commands.
92
-
93
- unzip instantclient-basic-macos.x64-12.1.0.2.0.zip
94
- unzip instantclient-sdk-macos.x64-12.1.0.2.0.zip
95
- unzip instantclient-sqlplus-macos.x64-12.1.0.2.0.zip
96
-
97
- Make a symbolic link to link the library.
98
-
99
- cd /opt/oracle/instantclient_12_1
100
- ln -s libclntsh.dylib.12.1 libclntsh.dylib
101
-
102
- Set the environment variable OCI_DIR while performing the following installation steps.
103
-
104
- export OCI_DIR=/opt/oracle/instantclient_12_1
105
-
106
- Installation
107
- ------------
108
-
109
- If you get a problem in the following steps, look at {file:docs/report-installation-issue.md}.
110
-
111
- ### gem package
112
-
113
- Run the following command.
17
+ If you have installed [Homebrew], use the following command:
114
18
 
115
- gem install ruby-oci8
19
+ ```shell
20
+ $ brew tap InstantClientTap/instantclient
21
+ $ brew install instantclient-basic # or instantclient-basiclite
22
+ $ brew install instantclient-sdk
23
+ $ brew install instantclient-sqlplus # (optionally)
24
+ ```
116
25
 
117
- ### tar.gz package
26
+ Otherwise, look at this [page][OTN] and set the environment variable
27
+ `OCI_DIR` to point the the directory where instant client is installed.
28
+ Ruby-oci8 installation script checks the directory.
118
29
 
119
- #### Download the source code
30
+ ```shell
31
+ export OCI_DIR=$HOME/Downloads/instantclient_19_8 # for example
32
+ ```
120
33
 
121
- Download the latest tar.gz package from [download page][].
34
+ Install ruby-oci8
35
+ -----------------
122
36
 
123
- #### Run make and install
37
+ Note that `/usr/bin/ruby` isn't available. You need to use [`rbenv`] or so.
124
38
 
125
- tar xvfz ruby-oci8-VERSION.tar.gz
126
- cd ruby-oci8-VERSION
127
- make
128
- make install
39
+ ```shell
40
+ $ gem install ruby-oci8
41
+ ```
129
42
 
130
- [download page]: https://bintray.com/kubo/generic/ruby-oci8
131
43
  [Homebrew]: http://brew.sh/
132
- [fix_oralib]: https://github.com/kubo/fix_oralib_osx
133
- [Oracle Technology Network]: http://www.oracle.com/technetwork/topics/intel-macsoft-096467.html
44
+ [OTN]: https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html#ic_osx_inst
45
+ [Xcode]: https://apps.apple.com/us/app/xcode/id497799835
46
+ [`rbenv`]: https://github.com/rbenv/rbenv
@@ -4,7 +4,6 @@
4
4
  %>
5
5
  #define API_WRAP_C 1
6
6
  #include "apiwrap.h"
7
- #define BLOCKING_FUNCTION_EPILOGUE(svcctx) do { (svcctx)->executing_thread = Qnil; } while (0)
8
7
 
9
8
  <%
10
9
  prev_name = ''
@@ -59,11 +58,9 @@ static void *oci8_<%=f.name%>_cb(void *user_data)
59
58
  %> data->rv = <%=f.name%>(<%= f.args.collect do |a| 'data->' + a.name; end.join(', ') %>);
60
59
  <% end %>
61
60
  <% if f.ret == 'sword'
62
- %> BLOCKING_FUNCTION_EPILOGUE(data->svcctx);
63
- return (void*)(VALUE)data->rv;
61
+ %> return (void*)(VALUE)data->rv;
64
62
  <% else
65
- %> BLOCKING_FUNCTION_EPILOGUE(data->svcctx);
66
- return NULL;
63
+ %> return NULL;
67
64
  <% end %>
68
65
  }
69
66
  #else
data/ext/oci8/apiwrap.yml CHANGED
@@ -83,6 +83,17 @@ OCIBindByPos:
83
83
  - ub4 *curelep
84
84
  - ub4 mode
85
85
 
86
+ # round trip: 0
87
+ OCIBindDynamic:
88
+ :version: 800
89
+ :args:
90
+ - OCIBind *bindp
91
+ - OCIError *errhp
92
+ - void *ictxp
93
+ - OCICallbackInBind icbfp
94
+ - void *octxp
95
+ - OCICallbackOutBind ocbfp
96
+
86
97
  # round trip: 0
87
98
  OCIBindObject:
88
99
  :version: 800
@@ -180,6 +191,15 @@ OCIDefineByPos:
180
191
  - ub2 *rcodep
181
192
  - ub4 mode
182
193
 
194
+ # round trip: 0
195
+ OCIDefineDynamic:
196
+ :version: 800
197
+ :args:
198
+ - OCIDefine *defnp
199
+ - OCIError *errhp
200
+ - dvoid *octxp
201
+ - OCICallbackDefine ocbfp
202
+
183
203
  # round trip: 0
184
204
  OCIDefineObject:
185
205
  :version: 800
data/ext/oci8/attr.c CHANGED
@@ -15,8 +15,9 @@ typedef struct {
15
15
  OCIRowid *ridp;
16
16
  } rowid_arg_t;
17
17
 
18
- static VALUE get_rowid_attr(rowid_arg_t *arg)
18
+ static VALUE get_rowid_attr(VALUE varg)
19
19
  {
20
+ rowid_arg_t *arg = (rowid_arg_t *)varg;
20
21
  oci8_base_t *base = arg->base;
21
22
  ub4 attrtype = arg->attrtype;
22
23
  char buf[MAX_ROWID_LEN];
@@ -36,8 +37,9 @@ static VALUE get_rowid_attr(rowid_arg_t *arg)
36
37
  return rb_external_str_new_with_enc(buf, buflen, rb_usascii_encoding());
37
38
  }
38
39
 
39
- static VALUE rowid_ensure(rowid_arg_t *arg)
40
+ static VALUE rowid_ensure(VALUE varg)
40
41
  {
42
+ rowid_arg_t *arg = (rowid_arg_t *)varg;
41
43
  if (arg->ridp != NULL) {
42
44
  OCIDescriptorFree(arg->ridp, OCI_DTYPE_ROWID);
43
45
  }
data/ext/oci8/bind.c CHANGED
@@ -11,6 +11,7 @@
11
11
  #endif
12
12
 
13
13
  static ID id_bind_type;
14
+ static ID id_charset_form;
14
15
  static VALUE sym_length;
15
16
  static VALUE sym_length_semantics;
16
17
  static VALUE sym_char;
@@ -25,6 +26,29 @@ typedef struct {
25
26
  ub1 csfrm;
26
27
  } oci8_bind_string_t;
27
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
+
28
52
  const oci8_handle_data_type_t oci8_bind_data_type = {
29
53
  {
30
54
  "OCI8::BindType::Base",
@@ -61,7 +85,7 @@ static void bind_string_set(oci8_bind_t *obind, void *data, void **null_structp,
61
85
  rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
62
86
  }
63
87
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
64
- vstr->size = RSTRING_LEN(val);
88
+ vstr->size = RSTRING_LENINT(val);
65
89
  }
66
90
 
67
91
  static void bind_string_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
@@ -171,7 +195,7 @@ static void bind_raw_set(oci8_bind_t *obind, void *data, void **null_structp, VA
171
195
  rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
172
196
  }
173
197
  memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
174
- vstr->size = RSTRING_LEN(val);
198
+ vstr->size = RSTRING_LENINT(val);
175
199
  }
176
200
 
177
201
  static const oci8_bind_data_type_t bind_raw_data_type = {
@@ -306,6 +330,295 @@ static VALUE bind_boolean_alloc(VALUE klass)
306
330
  return oci8_allocate_typeddata(klass, &bind_boolean_data_type.base);
307
331
  }
308
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
+ return str;
474
+ }
475
+
476
+ static void bind_long_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
477
+ {
478
+ chunk_buf_t *cb = (chunk_buf_t *)data;
479
+ ub4 len;
480
+ const char *buf;
481
+
482
+ if (IS_BIND_LONG(obind)) {
483
+ OCI8StringValue(val);
484
+ } else {
485
+ StringValue(val);
486
+ }
487
+ len = (ub4)RSTRING_LEN(val);
488
+ buf = RSTRING_PTR(val);
489
+ cb->tail = &cb->head;
490
+ while (1) {
491
+ chunk_t *chunk = next_chunk(cb);
492
+ if (len <= chunk->alloc_len) {
493
+ memcpy(chunk->buf, buf, len);
494
+ chunk->used_len = len;
495
+ break;
496
+ }
497
+ memcpy(chunk->buf, buf, chunk->alloc_len);
498
+ chunk->used_len = chunk->alloc_len;
499
+ len -= chunk->alloc_len;
500
+ buf += chunk->alloc_len;
501
+ }
502
+ }
503
+
504
+ static void bind_long_init(oci8_bind_t *obind, VALUE svc, VALUE val, VALUE param)
505
+ {
506
+ if (IS_BIND_LONG(obind)) {
507
+ oci8_bind_long_t *obl = (oci8_bind_long_t *)obind;
508
+ VALUE nchar;
509
+
510
+ if (rb_respond_to(param, id_charset_form)) {
511
+ VALUE csfrm = rb_funcall(param, id_charset_form, 0);
512
+ nchar = (csfrm == sym_nchar) ? Qtrue : Qfalse;
513
+ } else {
514
+ Check_Type(param, T_HASH);
515
+ nchar = rb_hash_aref(param, sym_nchar);
516
+ }
517
+
518
+ if (RTEST(nchar)) {
519
+ obl->csfrm = SQLCS_NCHAR; /* bind as NCHAR/NVARCHAR2 */
520
+ } else {
521
+ obl->csfrm = SQLCS_IMPLICIT; /* bind as CHAR/VARCHAR2 */
522
+ }
523
+ }
524
+ obind->value_sz = SB4MAXVAL;
525
+ obind->alloc_sz = sizeof(chunk_buf_t);
526
+ }
527
+
528
+ static void bind_long_init_elem(oci8_bind_t *obind, VALUE svc)
529
+ {
530
+ chunk_buf_t *cb = (chunk_buf_t *)obind->valuep;
531
+ ub4 idx = 0;
532
+
533
+ do {
534
+ cb[idx].tail = &cb[idx].head;
535
+ cb[idx].inpos = &cb[idx].head;
536
+ } while (++idx < obind->maxar_sz);
537
+ }
538
+
539
+ static void bind_long_post_bind_hook(oci8_bind_t *obind)
540
+ {
541
+ oci8_bind_long_t *ds = (oci8_bind_long_t *)obind;
542
+
543
+ if (IS_BIND_LONG(obind)) {
544
+ chker2(OCIAttrSet(obind->base.hp.ptr, obind->base.type, (void*)&ds->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp),
545
+ &obind->base);
546
+ }
547
+ switch (obind->base.type) {
548
+ case OCI_HTYPE_DEFINE:
549
+ chker2(OCIDefineDynamic(obind->base.hp.dfn, oci8_errhp, obind, define_callback),
550
+ &obind->base);
551
+ break;
552
+ case OCI_HTYPE_BIND:
553
+ chker2(OCIBindDynamic(obind->base.hp.bnd, oci8_errhp, obind, in_bind_callback,
554
+ obind, out_bind_callback),
555
+ &obind->base);
556
+ break;
557
+ }
558
+ }
559
+
560
+ static const oci8_bind_data_type_t bind_long_data_type = {
561
+ {
562
+ {
563
+ "OCI8::BindType::Long",
564
+ {
565
+ NULL,
566
+ oci8_handle_cleanup,
567
+ oci8_handle_size,
568
+ },
569
+ &oci8_bind_data_type.rb_data_type, NULL,
570
+ #ifdef RUBY_TYPED_WB_PROTECTED
571
+ RUBY_TYPED_WB_PROTECTED,
572
+ #endif
573
+ },
574
+ bind_long_free,
575
+ sizeof(oci8_bind_long_t)
576
+ },
577
+ bind_long_get,
578
+ bind_long_set,
579
+ bind_long_init,
580
+ bind_long_init_elem,
581
+ NULL,
582
+ SQLT_CHR,
583
+ bind_long_post_bind_hook,
584
+ };
585
+
586
+ static VALUE bind_long_alloc(VALUE klass)
587
+ {
588
+ return oci8_allocate_typeddata(klass, &bind_long_data_type.base);
589
+ }
590
+
591
+ static const oci8_bind_data_type_t bind_long_raw_data_type = {
592
+ {
593
+ {
594
+ "OCI8::BindType::LongRaw",
595
+ {
596
+ NULL,
597
+ oci8_handle_cleanup,
598
+ oci8_handle_size,
599
+ },
600
+ &oci8_bind_data_type.rb_data_type, NULL,
601
+ #ifdef RUBY_TYPED_WB_PROTECTED
602
+ RUBY_TYPED_WB_PROTECTED,
603
+ #endif
604
+ },
605
+ bind_long_free,
606
+ sizeof(oci8_bind_long_t)
607
+ },
608
+ bind_long_get,
609
+ bind_long_set,
610
+ bind_long_init,
611
+ bind_long_init_elem,
612
+ NULL,
613
+ SQLT_BIN,
614
+ bind_long_post_bind_hook,
615
+ };
616
+
617
+ static VALUE bind_long_raw_alloc(VALUE klass)
618
+ {
619
+ return oci8_allocate_typeddata(klass, &bind_long_raw_data_type.base);
620
+ }
621
+
309
622
  static VALUE oci8_bind_get(VALUE self)
310
623
  {
311
624
  oci8_bind_t *obind = TO_BIND(self);
@@ -320,11 +633,20 @@ static VALUE oci8_bind_get(VALUE self)
320
633
  return data_type->get(obind, (void*)((size_t)obind->valuep + obind->alloc_sz * idx), null_structp);
321
634
  }
322
635
 
323
- static VALUE oci8_bind_get_data(VALUE self)
636
+ static VALUE oci8_bind_get_data(int argc, VALUE *argv, VALUE self)
324
637
  {
325
638
  oci8_bind_t *obind = TO_BIND(self);
639
+ VALUE index;
326
640
 
327
- if (obind->maxar_sz == 0) {
641
+ rb_scan_args(argc, argv, "01", &index);
642
+ if (!NIL_P(index)) {
643
+ ub4 idx = NUM2UINT(index);
644
+ if (idx >= obind->maxar_sz) {
645
+ rb_raise(rb_eRuntimeError, "data index is too big. (%u for %u)", idx, obind->maxar_sz);
646
+ }
647
+ obind->curar_idx = idx;
648
+ return rb_funcall(self, oci8_id_get, 0);
649
+ } else if (obind->maxar_sz == 0) {
328
650
  obind->curar_idx = 0;
329
651
  return rb_funcall(self, oci8_id_get, 0);
330
652
  } else {
@@ -378,7 +700,7 @@ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
378
700
  ub4 idx;
379
701
  Check_Type(val, T_ARRAY);
380
702
 
381
- size = RARRAY_LEN(val);
703
+ size = RARRAY_LENINT(val);
382
704
  if (size > obind->maxar_sz) {
383
705
  rb_raise(rb_eRuntimeError, "over the max array size");
384
706
  }
@@ -391,6 +713,36 @@ static VALUE oci8_bind_set_data(VALUE self, VALUE val)
391
713
  return self;
392
714
  }
393
715
 
716
+ static VALUE get_initial_chunk_size(VALUE klass)
717
+ {
718
+ return UINT2NUM(initial_chunk_size);
719
+ }
720
+
721
+ static VALUE set_initial_chunk_size(VALUE klass, VALUE arg)
722
+ {
723
+ ub4 size = NUM2UINT(arg);
724
+ if (size == 0) {
725
+ rb_raise(rb_eArgError, "Could not set zero");
726
+ }
727
+ initial_chunk_size = size;
728
+ return arg;
729
+ }
730
+
731
+ static VALUE get_max_chunk_size(VALUE klass)
732
+ {
733
+ return UINT2NUM(max_chunk_size);
734
+ }
735
+
736
+ static VALUE set_max_chunk_size(VALUE klass, VALUE arg)
737
+ {
738
+ ub4 size = NUM2UINT(arg);
739
+ if (size == 0) {
740
+ rb_raise(rb_eArgError, "Could not set zero");
741
+ }
742
+ max_chunk_size = size;
743
+ return arg;
744
+ }
745
+
394
746
  static VALUE oci8_bind_initialize(VALUE self, VALUE svc, VALUE val, VALUE length, VALUE max_array_size)
395
747
  {
396
748
  oci8_bind_t *obind = TO_BIND(self);
@@ -456,6 +808,7 @@ void Init_oci8_bind(VALUE klass)
456
808
  {
457
809
  cOCI8BindTypeBase = klass;
458
810
  id_bind_type = rb_intern("bind_type");
811
+ id_charset_form = rb_intern("charset_form");
459
812
  sym_length = ID2SYM(rb_intern("length"));
460
813
  sym_length_semantics = ID2SYM(rb_intern("length_semantics"));
461
814
  sym_char = ID2SYM(rb_intern("char"));
@@ -464,9 +817,14 @@ void Init_oci8_bind(VALUE klass)
464
817
  rb_define_method(cOCI8BindTypeBase, "initialize", oci8_bind_initialize, 4);
465
818
  rb_define_method(cOCI8BindTypeBase, "get", oci8_bind_get, 0);
466
819
  rb_define_method(cOCI8BindTypeBase, "set", oci8_bind_set, 1);
467
- rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, 0);
820
+ rb_define_private_method(cOCI8BindTypeBase, "get_data", oci8_bind_get_data, -1);
468
821
  rb_define_private_method(cOCI8BindTypeBase, "set_data", oci8_bind_set_data, 1);
469
822
 
823
+ rb_define_singleton_method(klass, "initial_chunk_size", get_initial_chunk_size, 0);
824
+ rb_define_singleton_method(klass, "initial_chunk_size=", set_initial_chunk_size, 1);
825
+ rb_define_singleton_method(klass, "max_chunk_size", get_max_chunk_size, 0);
826
+ rb_define_singleton_method(klass, "max_chunk_size=", set_max_chunk_size, 1);
827
+
470
828
  /* register primitive data types. */
471
829
  oci8_define_bind_class("String", &bind_string_data_type, bind_string_alloc);
472
830
  oci8_define_bind_class("RAW", &bind_raw_data_type, bind_raw_alloc);
@@ -474,4 +832,6 @@ void Init_oci8_bind(VALUE klass)
474
832
  if (oracle_client_version >= ORAVER_12_1) {
475
833
  oci8_define_bind_class("Boolean", &bind_boolean_data_type, bind_boolean_alloc);
476
834
  }
835
+ klass = oci8_define_bind_class("Long", &bind_long_data_type, bind_long_alloc);
836
+ klass = oci8_define_bind_class("LongRaw", &bind_long_data_type, bind_long_raw_alloc);
477
837
  }