ruby-oci8 2.2.6.1 → 2.2.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
  }