ruby-oci8 2.0.6 → 2.1.0
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.
- data/ChangeLog +366 -19
- data/Makefile +2 -8
- data/NEWS +111 -0
- data/README +4 -85
- data/VERSION +1 -1
- data/dist-files +9 -2
- data/ext/oci8/.document +1 -0
- data/ext/oci8/apiwrap.c.tmpl +12 -2
- data/ext/oci8/apiwrap.yml +37 -21
- data/ext/oci8/attr.c +23 -74
- data/ext/oci8/bind.c +93 -225
- data/ext/oci8/connection_pool.c +201 -0
- data/ext/oci8/encoding.c +117 -24
- data/ext/oci8/env.c +5 -10
- data/ext/oci8/error.c +171 -189
- data/ext/oci8/extconf.rb +6 -2
- data/ext/oci8/lob.c +81 -79
- data/ext/oci8/metadata.c +42 -177
- data/ext/oci8/object.c +55 -28
- data/ext/oci8/oci8.c +426 -294
- data/ext/oci8/oci8.h +84 -51
- data/ext/oci8/oci8lib.c +75 -53
- data/ext/oci8/ocidatetime.c +67 -88
- data/ext/oci8/ocihandle.c +78 -37
- data/ext/oci8/ocinumber.c +166 -109
- data/ext/oci8/oraconf.rb +68 -157
- data/ext/oci8/oradate.c +2 -7
- data/ext/oci8/stmt.c +40 -183
- data/ext/oci8/thread_util.c +85 -0
- data/ext/oci8/thread_util.h +30 -0
- data/lib/oci8.rb.in +19 -13
- data/lib/oci8/.document +2 -0
- data/lib/oci8/bindtype.rb +62 -45
- data/lib/oci8/connection_pool.rb +118 -0
- data/lib/oci8/datetime.rb +304 -320
- data/lib/oci8/encoding-init.rb +62 -30
- data/lib/oci8/encoding.yml +3 -3
- data/lib/oci8/metadata.rb +552 -497
- data/lib/oci8/object.rb +9 -9
- data/lib/oci8/oci8.rb +161 -2
- data/lib/oci8/ocihandle.rb +427 -0
- data/lib/oci8/properties.rb +31 -1
- data/ruby-oci8.gemspec +10 -3
- data/test/README +41 -3
- data/test/config.rb +16 -0
- data/test/test_all.rb +3 -0
- data/test/test_bind_string.rb +106 -0
- data/test/test_break.rb +33 -7
- data/test/test_clob.rb +13 -10
- data/test/test_connection_pool.rb +125 -0
- data/test/test_connstr.rb +2 -2
- data/test/test_datetime.rb +26 -66
- data/test/test_encoding.rb +7 -3
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1356 -204
- data/test/test_oci8.rb +27 -8
- data/test/test_oranumber.rb +41 -0
- metadata +34 -9
- data/ext/oci8/xmldb.c +0 -383
data/ext/oci8/object.c
CHANGED
@@ -80,15 +80,17 @@ static VALUE oci8_tdo_setup(VALUE self, VALUE svc, VALUE md_obj)
|
|
80
80
|
OCIObjectUnpin(oci8_envhp, oci8_errhp, tdo->hp.tdo);
|
81
81
|
tdo->hp.tdo = NULL;
|
82
82
|
}
|
83
|
-
|
83
|
+
chker2(OCIAttrGet(md->hp.ptr, OCI_DTYPE_PARAM, &tdo_ref, NULL, OCI_ATTR_REF_TDO, oci8_errhp),
|
84
|
+
&svcctx->base);
|
84
85
|
if (tdo_ref == NULL)
|
85
86
|
return Qnil;
|
86
|
-
|
87
|
+
chker2(OCIObjectPin_nb(svcctx, oci8_envhp, oci8_errhp, tdo_ref, 0, OCI_PIN_ANY, OCI_DURATION_SESSION, OCI_LOCK_NONE, &tdo->hp.ptr),
|
88
|
+
&svcctx->base);
|
87
89
|
oci8_link_to_parent(tdo, &svcctx->base);
|
88
90
|
return self;
|
89
91
|
}
|
90
92
|
|
91
|
-
static
|
93
|
+
static oci8_base_vtable_t oci8_tdo_vtable = {
|
92
94
|
oci8_tdo_mark,
|
93
95
|
oci8_tdo_free,
|
94
96
|
sizeof(oci8_base_t)
|
@@ -233,11 +235,11 @@ static VALUE oci8_named_coll_get_coll_element(VALUE self, VALUE datatype, VALUE
|
|
233
235
|
if (*ind) {
|
234
236
|
return Qnil;
|
235
237
|
}
|
236
|
-
|
238
|
+
chker2(OCICollSize(oci8_envhp, oci8_errhp, coll, &size), &obj->base);
|
237
239
|
ary = rb_ary_new2(size);
|
238
240
|
for (idx = 0; idx < size; idx++) {
|
239
241
|
boolean exists;
|
240
|
-
|
242
|
+
chker2(OCICollGetElem(oci8_envhp, oci8_errhp, coll, idx, &exists, &data, (dvoid**)&ind), &obj->base);
|
241
243
|
if (exists) {
|
242
244
|
void *tmp;
|
243
245
|
if (datatype == INT2FIX(ATTR_NAMED_COLLECTION)) {
|
@@ -330,11 +332,13 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
330
332
|
cb_data.coll = (OCIColl*)*obj->instancep;
|
331
333
|
switch (FIX2INT(datatype)) {
|
332
334
|
case ATTR_STRING:
|
333
|
-
|
335
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_VARCHAR2, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
336
|
+
svcctx);
|
334
337
|
cb_data.indp = &cb_data.ind;
|
335
338
|
break;
|
336
339
|
case ATTR_RAW:
|
337
|
-
|
340
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_RAW, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
341
|
+
svcctx);
|
338
342
|
cb_data.indp = &cb_data.ind;
|
339
343
|
break;
|
340
344
|
case ATTR_OCINUMBER:
|
@@ -357,14 +361,18 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
357
361
|
case ATTR_NAMED_TYPE:
|
358
362
|
Check_Object(typeinfo, cOCI8TDO);
|
359
363
|
tdo = DATA_PTR(typeinfo);
|
360
|
-
|
361
|
-
|
364
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_OBJECT, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
365
|
+
svcctx);
|
366
|
+
chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
|
367
|
+
svcctx);
|
362
368
|
break;
|
363
369
|
case ATTR_NAMED_COLLECTION:
|
364
370
|
Check_Object(typeinfo, cOCI8TDO);
|
365
371
|
tdo = DATA_PTR(typeinfo);
|
366
|
-
|
367
|
-
|
372
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_NAMEDCOLLECTION, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr),
|
373
|
+
svcctx);
|
374
|
+
chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp),
|
375
|
+
svcctx);
|
368
376
|
break;
|
369
377
|
case ATTR_CLOB:
|
370
378
|
case ATTR_NCLOB:
|
@@ -381,6 +389,7 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
381
389
|
set_coll_element_func(&cb_data);
|
382
390
|
set_coll_element_ensure(&cb_data);
|
383
391
|
#endif
|
392
|
+
*ind = 0;
|
384
393
|
return Qnil;
|
385
394
|
}
|
386
395
|
|
@@ -395,9 +404,9 @@ static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data)
|
|
395
404
|
sb4 idx;
|
396
405
|
void *elem_ptr;
|
397
406
|
|
398
|
-
|
407
|
+
chkerr(OCICollSize(oci8_envhp, oci8_errhp, coll, &size));
|
399
408
|
if (RARRAY_LEN(val) < size) {
|
400
|
-
|
409
|
+
chkerr(OCICollTrim(oci8_envhp, oci8_errhp, size - RARRAY_LEN(val), coll));
|
401
410
|
}
|
402
411
|
for (idx = 0; idx < RARRAY_LEN(val); idx++) {
|
403
412
|
switch (FIX2INT(datatype)) {
|
@@ -422,9 +431,9 @@ static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data)
|
|
422
431
|
break;
|
423
432
|
}
|
424
433
|
if (idx < size) {
|
425
|
-
|
434
|
+
chkerr(OCICollAssignElem(oci8_envhp, oci8_errhp, idx, elem_ptr, cb_data->indp, cb_data->coll));
|
426
435
|
} else {
|
427
|
-
|
436
|
+
chkerr(OCICollAppend(oci8_envhp, oci8_errhp, elem_ptr, cb_data->indp, coll));
|
428
437
|
}
|
429
438
|
}
|
430
439
|
return Qnil;
|
@@ -468,13 +477,13 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
|
|
468
477
|
switch (FIX2INT(datatype)) {
|
469
478
|
case ATTR_STRING:
|
470
479
|
OCI8StringValue(val);
|
471
|
-
|
480
|
+
chkerr(OCIStringAssignText(oci8_envhp, oci8_errhp,
|
472
481
|
RSTRING_ORATEXT(val), RSTRING_LEN(val),
|
473
482
|
(OCIString **)data));
|
474
483
|
break;
|
475
484
|
case ATTR_RAW:
|
476
485
|
StringValue(val);
|
477
|
-
|
486
|
+
chkerr(OCIRawAssignBytes(oci8_envhp, oci8_errhp,
|
478
487
|
RSTRING_ORATEXT(val), RSTRING_LEN(val),
|
479
488
|
(OCIRaw **)data));
|
480
489
|
break;
|
@@ -536,7 +545,7 @@ static void set_attribute(VALUE self, VALUE datatype, VALUE typeinfo, void *data
|
|
536
545
|
*ind = 0;
|
537
546
|
}
|
538
547
|
|
539
|
-
static
|
548
|
+
static oci8_base_vtable_t oci8_named_type_vtable = {
|
540
549
|
oci8_named_type_mark,
|
541
550
|
oci8_named_type_free,
|
542
551
|
sizeof(oci8_named_type_t)
|
@@ -624,13 +633,32 @@ static void bind_named_type_init_elem(oci8_bind_t *obind, VALUE svc)
|
|
624
633
|
obj->null_structp = (char**)&obind->u.null_structs[idx];
|
625
634
|
oci8_link_to_parent(&obj->base, &obind->base);
|
626
635
|
|
627
|
-
|
628
|
-
|
636
|
+
chker2(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->base.hp.svc, tc, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, (dvoid**)obj->instancep),
|
637
|
+
&svcctx->base);
|
638
|
+
chker2(OCIObjectGetInd(oci8_envhp, oci8_errhp, (dvoid*)*obj->instancep, (dvoid**)obj->null_structp),
|
639
|
+
&svcctx->base);
|
629
640
|
*(OCIInd*)*obj->null_structp = -1;
|
630
641
|
} while (++idx < obind->maxar_sz);
|
631
642
|
}
|
632
643
|
|
633
|
-
static
|
644
|
+
static void bind_name_type_post_bind_hook(oci8_bind_t *obind)
|
645
|
+
{
|
646
|
+
oci8_base_t *tdo = DATA_PTR(obind->tdo);
|
647
|
+
switch (obind->base.type) {
|
648
|
+
case OCI_HTYPE_DEFINE:
|
649
|
+
chker2(OCIDefineObject(obind->base.hp.dfn, oci8_errhp, tdo->hp.tdo,
|
650
|
+
obind->valuep, 0, obind->u.null_structs, 0),
|
651
|
+
&obind->base);
|
652
|
+
break;
|
653
|
+
case OCI_HTYPE_BIND:
|
654
|
+
chker2(OCIBindObject(obind->base.hp.bnd, oci8_errhp, tdo->hp.tdo,
|
655
|
+
obind->valuep, 0, obind->u.null_structs, 0),
|
656
|
+
&obind->base);
|
657
|
+
break;
|
658
|
+
}
|
659
|
+
}
|
660
|
+
|
661
|
+
static const oci8_bind_vtable_t bind_named_type_vtable = {
|
634
662
|
{
|
635
663
|
bind_named_type_mark,
|
636
664
|
bind_named_type_free,
|
@@ -641,9 +669,8 @@ static const oci8_bind_class_t bind_named_type_class = {
|
|
641
669
|
bind_named_type_init,
|
642
670
|
bind_named_type_init_elem,
|
643
671
|
NULL,
|
644
|
-
|
645
|
-
|
646
|
-
SQLT_NTY
|
672
|
+
SQLT_NTY,
|
673
|
+
bind_name_type_post_bind_hook,
|
647
674
|
};
|
648
675
|
|
649
676
|
void Init_oci_object(VALUE cOCI8)
|
@@ -652,7 +679,7 @@ void Init_oci_object(VALUE cOCI8)
|
|
652
679
|
id_set_attributes = rb_intern("attributes=");
|
653
680
|
|
654
681
|
/* OCI8::TDO */
|
655
|
-
cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &
|
682
|
+
cOCI8TDO = oci8_define_class_under(cOCI8, "TDO", &oci8_tdo_vtable);
|
656
683
|
rb_define_private_method(cOCI8TDO, "setup", oci8_tdo_setup, 2);
|
657
684
|
rb_define_const(cOCI8TDO, "ATTR_STRING", INT2FIX(ATTR_STRING));
|
658
685
|
rb_define_const(cOCI8TDO, "ATTR_RAW", INT2FIX(ATTR_RAW));
|
@@ -681,7 +708,7 @@ void Init_oci_object(VALUE cOCI8)
|
|
681
708
|
rb_define_const(cOCI8TDO, "ALIGNMENT_OF_DOUBLE", INT2FIX(ALIGNMENT_OF(double)));
|
682
709
|
|
683
710
|
/* OCI8::NamedType */
|
684
|
-
cOCI8NamedType = oci8_define_class_under(cOCI8, "NamedType", &
|
711
|
+
cOCI8NamedType = oci8_define_class_under(cOCI8, "NamedType", &oci8_named_type_vtable);
|
685
712
|
rb_define_method(cOCI8NamedType, "initialize", oci8_named_type_initialize, 0);
|
686
713
|
rb_define_method(cOCI8NamedType, "tdo", oci8_named_type_tdo, 0);
|
687
714
|
rb_define_private_method(cOCI8NamedType, "get_attribute", oci8_named_type_get_attribute, 4);
|
@@ -690,12 +717,12 @@ void Init_oci_object(VALUE cOCI8)
|
|
690
717
|
rb_define_method(cOCI8NamedType, "null=", oci8_named_type_set_null, 1);
|
691
718
|
|
692
719
|
/* OCI8::NamedCollection */
|
693
|
-
cOCI8NamedCollection = oci8_define_class_under(cOCI8, "NamedCollection", &
|
720
|
+
cOCI8NamedCollection = oci8_define_class_under(cOCI8, "NamedCollection", &oci8_named_type_vtable);
|
694
721
|
rb_define_method(cOCI8NamedCollection, "initialize", oci8_named_type_initialize, 0);
|
695
722
|
rb_define_method(cOCI8NamedCollection, "tdo", oci8_named_type_tdo, 0);
|
696
723
|
rb_define_private_method(cOCI8NamedCollection, "get_coll_element", oci8_named_coll_get_coll_element, 2);
|
697
724
|
rb_define_private_method(cOCI8NamedCollection, "set_coll_element", oci8_named_coll_set_coll_element, 3);
|
698
725
|
|
699
726
|
/* OCI8::BindType::NamedType */
|
700
|
-
cOCI8BindNamedType = oci8_define_bind_class("NamedType", &
|
727
|
+
cOCI8BindNamedType = oci8_define_bind_class("NamedType", &bind_named_type_vtable);
|
701
728
|
}
|
data/ext/oci8/oci8.c
CHANGED
@@ -2,10 +2,11 @@
|
|
2
2
|
/*
|
3
3
|
* oci8.c - part of ruby-oci8
|
4
4
|
*
|
5
|
-
* Copyright (C) 2002-
|
5
|
+
* Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
|
6
6
|
*
|
7
7
|
*/
|
8
8
|
#include "oci8.h"
|
9
|
+
#include <errno.h>
|
9
10
|
#ifdef HAVE_UNISTD_H
|
10
11
|
#include <unistd.h> /* getpid() */
|
11
12
|
#endif
|
@@ -30,33 +31,107 @@ extern rb_pid_t rb_w32_getpid(void);
|
|
30
31
|
#define OCI_ATTR_CLIENT_INFO 368
|
31
32
|
#endif
|
32
33
|
|
34
|
+
#define OCI8_STATE_SESSION_BEGIN_WAS_CALLED 0x01
|
35
|
+
#define OCI8_STATE_SERVER_ATTACH_WAS_CALLED 0x02
|
36
|
+
#define OCI8_STATE_CPOOL 0x04
|
37
|
+
|
33
38
|
static VALUE cOCI8;
|
39
|
+
static VALUE cSession;
|
40
|
+
static VALUE cServer;
|
41
|
+
static ID id_at_session_handle;
|
42
|
+
static ID id_at_server_handle;
|
43
|
+
|
44
|
+
typedef struct oci8_svcctx_associate {
|
45
|
+
oci8_base_t base;
|
46
|
+
oci8_svcctx_t *svcctx;
|
47
|
+
} oci8_svcctx_associate_t;
|
48
|
+
|
49
|
+
static void oci8_svcctx_associate_free(oci8_base_t *base)
|
50
|
+
{
|
51
|
+
base->type = 0;
|
52
|
+
base->hp.ptr = NULL;
|
53
|
+
}
|
54
|
+
|
55
|
+
static oci8_base_vtable_t oci8_svcctx_associate_vtable = {
|
56
|
+
NULL,
|
57
|
+
oci8_svcctx_associate_free,
|
58
|
+
sizeof(oci8_svcctx_associate_t),
|
59
|
+
};
|
60
|
+
|
61
|
+
static void copy_session_handle(oci8_svcctx_t *svcctx)
|
62
|
+
{
|
63
|
+
VALUE obj = rb_ivar_get(svcctx->base.self, id_at_session_handle);
|
64
|
+
oci8_base_t *base;
|
65
|
+
|
66
|
+
Check_Handle(obj, cSession, base);
|
67
|
+
base->type = OCI_HTYPE_SESSION;
|
68
|
+
base->hp.usrhp = svcctx->usrhp;
|
69
|
+
}
|
70
|
+
|
71
|
+
static void copy_server_handle(oci8_svcctx_t *svcctx)
|
72
|
+
{
|
73
|
+
VALUE obj = rb_ivar_get(svcctx->base.self, id_at_server_handle);
|
74
|
+
oci8_base_t *base;
|
75
|
+
|
76
|
+
Check_Handle(obj, cServer, base);
|
77
|
+
base->type = OCI_HTYPE_SERVER;
|
78
|
+
base->hp.srvhp = svcctx->srvhp;
|
79
|
+
}
|
34
80
|
|
35
81
|
static void oci8_svcctx_free(oci8_base_t *base)
|
36
82
|
{
|
37
83
|
oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
84
|
+
if (svcctx->logoff_strategy != NULL) {
|
85
|
+
const oci8_logoff_strategy_t *strategy = svcctx->logoff_strategy;
|
86
|
+
void *data = strategy->prepare(svcctx);
|
87
|
+
int rv;
|
88
|
+
svcctx->base.type = 0;
|
89
|
+
svcctx->logoff_strategy = NULL;
|
90
|
+
rv = oci8_run_native_thread(strategy->execute, data);
|
91
|
+
if (rv != 0) {
|
92
|
+
errno = rv;
|
93
|
+
#ifdef WIN32
|
94
|
+
rb_sys_fail("_beginthread");
|
95
|
+
#else
|
96
|
+
rb_sys_fail("pthread_create");
|
97
|
+
#endif
|
98
|
+
}
|
46
99
|
}
|
100
|
+
svcctx->base.type = 0;
|
47
101
|
}
|
48
102
|
|
49
|
-
static
|
103
|
+
static void oci8_svcctx_init(oci8_base_t *base)
|
104
|
+
{
|
105
|
+
oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
|
106
|
+
VALUE obj;
|
107
|
+
|
108
|
+
svcctx->executing_thread = Qnil;
|
109
|
+
/* set session handle */
|
110
|
+
obj = rb_obj_alloc(cSession);
|
111
|
+
rb_ivar_set(base->self, id_at_session_handle, obj);
|
112
|
+
oci8_link_to_parent(DATA_PTR(obj), base);
|
113
|
+
/* set server handle */
|
114
|
+
obj = rb_obj_alloc(cServer);
|
115
|
+
rb_ivar_set(base->self, id_at_server_handle, obj);
|
116
|
+
oci8_link_to_parent(DATA_PTR(obj), base);
|
117
|
+
|
118
|
+
svcctx->pid = getpid();
|
119
|
+
svcctx->is_autocommit = 0;
|
120
|
+
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
121
|
+
svcctx->non_blocking = 1;
|
122
|
+
#endif
|
123
|
+
svcctx->long_read_len = INT2FIX(65535);
|
124
|
+
}
|
125
|
+
|
126
|
+
static oci8_base_vtable_t oci8_svcctx_vtable = {
|
50
127
|
NULL,
|
51
128
|
oci8_svcctx_free,
|
52
|
-
sizeof(oci8_svcctx_t)
|
129
|
+
sizeof(oci8_svcctx_t),
|
130
|
+
oci8_svcctx_init,
|
53
131
|
};
|
54
132
|
|
55
133
|
static VALUE oracle_client_vernum; /* Oracle client version number */
|
56
|
-
static VALUE sym_SYSDBA;
|
57
|
-
static VALUE sym_SYSOPER;
|
58
134
|
static ID id_at_prefetch_rows;
|
59
|
-
static ID id_at_username;
|
60
135
|
static ID id_set_prefetch_rows;
|
61
136
|
|
62
137
|
static VALUE oci8_s_oracle_client_vernum(VALUE klass)
|
@@ -64,6 +139,27 @@ static VALUE oci8_s_oracle_client_vernum(VALUE klass)
|
|
64
139
|
return oracle_client_vernum;
|
65
140
|
}
|
66
141
|
|
142
|
+
static VALUE oci8_s_set_property(VALUE klass, VALUE name, VALUE val)
|
143
|
+
{
|
144
|
+
const char *name_str;
|
145
|
+
|
146
|
+
Check_Type(name, T_SYMBOL);
|
147
|
+
name_str = rb_id2name(SYM2ID(name));
|
148
|
+
if (strcmp(name_str, "float_conversion_type") == 0) {
|
149
|
+
const char *val_str;
|
150
|
+
Check_Type(val, T_SYMBOL);
|
151
|
+
val_str = rb_id2name(SYM2ID(val));
|
152
|
+
if (strcmp(val_str, "ruby") == 0) {
|
153
|
+
oci8_float_conversion_type_is_ruby = 1;
|
154
|
+
} else if (strcmp(val_str, "oracle") == 0) {
|
155
|
+
oci8_float_conversion_type_is_ruby = 0;
|
156
|
+
} else {
|
157
|
+
rb_raise(rb_eArgError, "float_conversion_type's value should be either :ruby or :oracle.");
|
158
|
+
}
|
159
|
+
}
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
|
67
163
|
/*
|
68
164
|
* call-seq:
|
69
165
|
* OCI8.error_message(message_no) -> string
|
@@ -87,7 +183,7 @@ static VALUE oci8_s_error_message(VALUE klass, VALUE msgid)
|
|
87
183
|
}
|
88
184
|
|
89
185
|
#define CONN_STR_REGEX "/^([^(\\s|\\@)]*)\\/([^(\\s|\\@)]*)(?:\\@(\\S+))?(?:\\s+as\\s+(\\S*)\\s*)?$/i"
|
90
|
-
|
186
|
+
void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode)
|
91
187
|
{
|
92
188
|
static VALUE re = Qnil;
|
93
189
|
if (NIL_P(re)) {
|
@@ -106,14 +202,7 @@ static void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pas
|
|
106
202
|
*pass = Qnil;
|
107
203
|
}
|
108
204
|
if (!NIL_P(*mode)) {
|
109
|
-
|
110
|
-
SafeStringValue(*mode);
|
111
|
-
ptr = RSTRING_PTR(*mode);
|
112
|
-
if (strcasecmp(ptr, "SYSDBA") == 0) {
|
113
|
-
*mode = sym_SYSDBA;
|
114
|
-
} else if (strcasecmp(ptr, "SYSOPER") == 0) {
|
115
|
-
*mode = sym_SYSOPER;
|
116
|
-
}
|
205
|
+
*mode = ID2SYM(rb_to_id(rb_funcall(*mode, rb_intern("upcase"), 0)));
|
117
206
|
}
|
118
207
|
} else {
|
119
208
|
rb_raise(rb_eArgError, "invalid connect string \"%s\" (expect \"username/password[@(tns_name|//host[:port]/service_name)][ as (sysdba|sysoper)]\"", RSTRING_PTR(conn_str));
|
@@ -143,184 +232,291 @@ static VALUE oci8_parse_connect_string(VALUE self, VALUE conn_str)
|
|
143
232
|
return rb_ary_new3(4, user, pass, dbname, mode);
|
144
233
|
}
|
145
234
|
|
235
|
+
/*
|
236
|
+
* Logoff strategy for sessions connected by OCILogon.
|
237
|
+
*/
|
238
|
+
typedef struct {
|
239
|
+
OCISvcCtx *svchp;
|
240
|
+
OCISession *usrhp;
|
241
|
+
OCIServer *srvhp;
|
242
|
+
} simple_logoff_arg_t;
|
243
|
+
|
244
|
+
static void *simple_logoff_prepare(oci8_svcctx_t *svcctx)
|
245
|
+
{
|
246
|
+
simple_logoff_arg_t *sla = xmalloc(sizeof(simple_logoff_arg_t));
|
247
|
+
sla->svchp = svcctx->base.hp.svc;
|
248
|
+
sla->usrhp = svcctx->usrhp;
|
249
|
+
sla->srvhp = svcctx->srvhp;
|
250
|
+
svcctx->usrhp = NULL;
|
251
|
+
svcctx->srvhp = NULL;
|
252
|
+
return sla;
|
253
|
+
}
|
254
|
+
|
255
|
+
static VALUE simple_logoff_execute(void *arg)
|
256
|
+
{
|
257
|
+
simple_logoff_arg_t *sla = (simple_logoff_arg_t *)arg;
|
258
|
+
OCIError *errhp = oci8_errhp;
|
259
|
+
sword rv;
|
260
|
+
|
261
|
+
OCITransRollback(sla->svchp, errhp, OCI_DEFAULT);
|
262
|
+
rv = OCILogoff(sla->svchp, errhp);
|
263
|
+
xfree(sla);
|
264
|
+
return (VALUE)rv;
|
265
|
+
}
|
266
|
+
|
267
|
+
static const oci8_logoff_strategy_t simple_logoff = {
|
268
|
+
simple_logoff_prepare,
|
269
|
+
simple_logoff_execute,
|
270
|
+
};
|
271
|
+
|
272
|
+
/*
|
273
|
+
* Logoff strategy for sessions connected by OCIServerAttach and OCISessionBegin.
|
274
|
+
*/
|
275
|
+
|
276
|
+
typedef struct {
|
277
|
+
OCISvcCtx *svchp;
|
278
|
+
OCISession *usrhp;
|
279
|
+
OCIServer *srvhp;
|
280
|
+
unsigned char state;
|
281
|
+
} complex_logoff_arg_t;
|
282
|
+
|
283
|
+
static void *complex_logoff_prepare(oci8_svcctx_t *svcctx)
|
284
|
+
{
|
285
|
+
complex_logoff_arg_t *cla = xmalloc(sizeof(complex_logoff_arg_t));
|
286
|
+
cla->svchp = svcctx->base.hp.svc;
|
287
|
+
cla->usrhp = svcctx->usrhp;
|
288
|
+
cla->srvhp = svcctx->srvhp;
|
289
|
+
cla->state = svcctx->state;
|
290
|
+
svcctx->usrhp = NULL;
|
291
|
+
svcctx->srvhp = NULL;
|
292
|
+
svcctx->state = 0;
|
293
|
+
return cla;
|
294
|
+
}
|
295
|
+
|
296
|
+
static VALUE complex_logoff_execute(void *arg)
|
297
|
+
{
|
298
|
+
complex_logoff_arg_t *cla = (complex_logoff_arg_t *)arg;
|
299
|
+
OCIError *errhp = oci8_errhp;
|
300
|
+
sword rv = OCI_SUCCESS;
|
301
|
+
|
302
|
+
OCITransRollback(cla->svchp, errhp, OCI_DEFAULT);
|
303
|
+
|
304
|
+
if (cla->state & OCI8_STATE_SESSION_BEGIN_WAS_CALLED) {
|
305
|
+
rv = OCISessionEnd(cla->svchp, oci8_errhp, cla->usrhp, OCI_DEFAULT);
|
306
|
+
cla->state &= ~OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
|
307
|
+
}
|
308
|
+
if (cla->state & OCI8_STATE_SERVER_ATTACH_WAS_CALLED) {
|
309
|
+
rv = OCIServerDetach(cla->srvhp, oci8_errhp, OCI_DEFAULT);
|
310
|
+
cla->state &= ~OCI8_STATE_SERVER_ATTACH_WAS_CALLED;
|
311
|
+
}
|
312
|
+
if (cla->usrhp != NULL) {
|
313
|
+
OCIHandleFree(cla->usrhp, OCI_HTYPE_SESSION);
|
314
|
+
}
|
315
|
+
if (cla->srvhp != NULL) {
|
316
|
+
OCIHandleFree(cla->srvhp, OCI_HTYPE_SERVER);
|
317
|
+
}
|
318
|
+
if (cla->svchp != NULL) {
|
319
|
+
OCIHandleFree(cla->svchp, OCI_HTYPE_SVCCTX);
|
320
|
+
}
|
321
|
+
xfree(cla);
|
322
|
+
return (VALUE)rv;
|
323
|
+
}
|
324
|
+
|
325
|
+
static const oci8_logoff_strategy_t complex_logoff = {
|
326
|
+
complex_logoff_prepare,
|
327
|
+
complex_logoff_execute,
|
328
|
+
};
|
329
|
+
|
146
330
|
/*
|
147
331
|
* call-seq:
|
148
|
-
*
|
149
|
-
*
|
150
|
-
* Connects to an Oracle database server by +username+ and +password+
|
151
|
-
* at +dbname+ as +privilege+.
|
152
|
-
*
|
153
|
-
* === connecting to the local server
|
154
|
-
*
|
155
|
-
* Set +username+ and +password+ or pass "username/password" as a
|
156
|
-
* single argument.
|
157
|
-
*
|
158
|
-
* OCI8.new('scott', 'tiger')
|
159
|
-
* or
|
160
|
-
* OCI8.new('scott/tiger')
|
161
|
-
*
|
162
|
-
* === connecting to a remote server
|
163
|
-
*
|
164
|
-
* Set +username+, +password+ and +dbname+ or pass
|
165
|
-
* "username/password@dbname" as a single argument.
|
332
|
+
* logon(username, password, dbname) -> connection
|
166
333
|
*
|
167
|
-
*
|
168
|
-
* or
|
169
|
-
* OCI8.new('scott/tiger@orcl.world')
|
334
|
+
* <b>internal use only</b>
|
170
335
|
*
|
171
|
-
*
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
*
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
336
|
+
* Creates a simple logon session by the OCI function OCILogon().
|
337
|
+
*/
|
338
|
+
static VALUE oci8_logon(VALUE self, VALUE username, VALUE password, VALUE dbname)
|
339
|
+
{
|
340
|
+
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
341
|
+
|
342
|
+
if (svcctx->logoff_strategy != NULL) {
|
343
|
+
rb_raise(rb_eRuntimeError, "Could not reuse the session.");
|
344
|
+
}
|
345
|
+
|
346
|
+
/* check arugmnets */
|
347
|
+
OCI8SafeStringValue(username);
|
348
|
+
OCI8SafeStringValue(password);
|
349
|
+
if (!NIL_P(dbname)) {
|
350
|
+
OCI8SafeStringValue(dbname);
|
351
|
+
}
|
352
|
+
|
353
|
+
/* logon */
|
354
|
+
svcctx->base.type = OCI_HTYPE_SVCCTX;
|
355
|
+
chker2(OCILogon_nb(svcctx, oci8_envhp, oci8_errhp, &svcctx->base.hp.svc,
|
356
|
+
RSTRING_ORATEXT(username), RSTRING_LEN(username),
|
357
|
+
RSTRING_ORATEXT(password), RSTRING_LEN(password),
|
358
|
+
NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
|
359
|
+
NIL_P(dbname) ? 0 : RSTRING_LEN(dbname)),
|
360
|
+
&svcctx->base);
|
361
|
+
svcctx->logoff_strategy = &simple_logoff;
|
362
|
+
|
363
|
+
/* setup the session handle */
|
364
|
+
chker2(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->usrhp, 0, OCI_ATTR_SESSION, oci8_errhp),
|
365
|
+
&svcctx->base);
|
366
|
+
copy_session_handle(svcctx);
|
367
|
+
|
368
|
+
/* setup the server handle */
|
369
|
+
chker2(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp),
|
370
|
+
&svcctx->base);
|
371
|
+
copy_server_handle(svcctx);
|
372
|
+
|
373
|
+
return Qnil;
|
374
|
+
}
|
375
|
+
|
376
|
+
/*
|
377
|
+
* call-seq:
|
378
|
+
* allocate_handles()
|
185
379
|
*
|
186
|
-
*
|
187
|
-
* or
|
188
|
-
* OCI8.new('sys/change_on_install as sysdba')
|
380
|
+
* <b>internal use only</b>
|
189
381
|
*
|
190
|
-
*
|
382
|
+
* Allocates a service context handle, a session handle and a
|
383
|
+
* server handle to use explicit attach and begin-session calls.
|
384
|
+
*/
|
385
|
+
static VALUE oci8_allocate_handles(VALUE self)
|
386
|
+
{
|
387
|
+
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
388
|
+
sword rv;
|
389
|
+
|
390
|
+
if (svcctx->logoff_strategy != NULL) {
|
391
|
+
rb_raise(rb_eRuntimeError, "Could not reuse the session.");
|
392
|
+
}
|
393
|
+
svcctx->logoff_strategy = &complex_logoff;
|
394
|
+
svcctx->state = 0;
|
395
|
+
|
396
|
+
/* allocate a service context handle */
|
397
|
+
rv = OCIHandleAlloc(oci8_envhp, &svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, 0, 0);
|
398
|
+
if (rv != OCI_SUCCESS)
|
399
|
+
oci8_env_raise(oci8_envhp, rv);
|
400
|
+
svcctx->base.type = OCI_HTYPE_SVCCTX;
|
401
|
+
|
402
|
+
/* alocalte a session handle */
|
403
|
+
rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->usrhp, OCI_HTYPE_SESSION, 0, 0);
|
404
|
+
if (rv != OCI_SUCCESS)
|
405
|
+
oci8_env_raise(oci8_envhp, rv);
|
406
|
+
copy_session_handle(svcctx);
|
407
|
+
|
408
|
+
/* alocalte a server handle */
|
409
|
+
rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0);
|
410
|
+
if (rv != OCI_SUCCESS)
|
411
|
+
oci8_env_raise(oci8_envhp, rv);
|
412
|
+
copy_server_handle(svcctx);
|
413
|
+
return self;
|
414
|
+
}
|
415
|
+
|
416
|
+
/*
|
417
|
+
* call-seq:
|
418
|
+
* session_handle -> a session handle
|
191
419
|
*
|
192
|
-
*
|
420
|
+
* <b>internal use only</b>
|
193
421
|
*
|
194
|
-
*
|
195
|
-
|
196
|
-
|
422
|
+
* Returns a session handle associated with the service context handle.
|
423
|
+
*/
|
424
|
+
static VALUE oci8_get_session_handle(VALUE self)
|
425
|
+
{
|
426
|
+
return rb_ivar_get(self, id_at_session_handle);
|
427
|
+
}
|
428
|
+
|
429
|
+
/*
|
430
|
+
* call-seq:
|
431
|
+
* server_handle -> a server handle
|
197
432
|
*
|
198
|
-
*
|
433
|
+
* <b>internal use only</b>
|
199
434
|
*
|
200
|
-
*
|
201
|
-
|
202
|
-
|
435
|
+
* Returns a server handle associated with the service context handle.
|
436
|
+
*/
|
437
|
+
static VALUE oci8_get_server_handle(VALUE self)
|
438
|
+
{
|
439
|
+
return rb_ivar_get(self, id_at_server_handle);
|
440
|
+
}
|
441
|
+
|
442
|
+
/*
|
443
|
+
* call-seq:
|
444
|
+
* server_attach(dbname, mode)
|
203
445
|
*
|
204
|
-
*
|
446
|
+
* <b>internal use only</b>
|
205
447
|
*
|
206
|
-
*
|
207
|
-
|
448
|
+
* Attachs to the server by the OCI function OCIServerAttach().
|
449
|
+
*/
|
450
|
+
static VALUE oci8_server_attach(VALUE self, VALUE dbname, VALUE attach_mode)
|
451
|
+
{
|
452
|
+
oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
|
453
|
+
ub4 mode = NUM2UINT(attach_mode);
|
454
|
+
|
455
|
+
if (svcctx->logoff_strategy != &complex_logoff) {
|
456
|
+
rb_raise(rb_eRuntimeError, "Use this method only for the service context handle created by OCI8#server_handle().");
|
457
|
+
}
|
458
|
+
if (svcctx->state & OCI8_STATE_SERVER_ATTACH_WAS_CALLED) {
|
459
|
+
rb_raise(rb_eRuntimeError, "Could not use this method twice.");
|
460
|
+
}
|
461
|
+
|
462
|
+
/* check arguments */
|
463
|
+
if (!NIL_P(dbname)) {
|
464
|
+
OCI8SafeStringValue(dbname);
|
465
|
+
}
|
466
|
+
|
467
|
+
/* attach to the server */
|
468
|
+
chker2(OCIServerAttach_nb(svcctx, svcctx->srvhp, oci8_errhp,
|
469
|
+
NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
|
470
|
+
NIL_P(dbname) ? 0 : RSTRING_LEN(dbname),
|
471
|
+
mode),
|
472
|
+
&svcctx->base);
|
473
|
+
chker2(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX,
|
474
|
+
svcctx->srvhp, 0, OCI_ATTR_SERVER,
|
475
|
+
oci8_errhp),
|
476
|
+
&svcctx->base);
|
477
|
+
svcctx->state |= OCI8_STATE_SERVER_ATTACH_WAS_CALLED;
|
478
|
+
if (mode & OCI_CPOOL) {
|
479
|
+
svcctx->state |= OCI8_STATE_CPOOL;
|
480
|
+
}
|
481
|
+
return self;
|
482
|
+
}
|
483
|
+
|
484
|
+
/*
|
485
|
+
* call-seq:
|
486
|
+
* session_begin(cred, mode)
|
208
487
|
*
|
209
|
-
*
|
210
|
-
* or
|
211
|
-
* OCI8.new('proxy_user_name[end_user_name]/proxy_password')
|
488
|
+
* <b>internal use only</b>
|
212
489
|
*
|
490
|
+
* Begins the session by the OCI function OCISessionBegin().
|
213
491
|
*/
|
214
|
-
static VALUE
|
492
|
+
static VALUE oci8_session_begin(VALUE self, VALUE cred, VALUE mode)
|
215
493
|
{
|
216
|
-
VALUE vusername;
|
217
|
-
VALUE vpassword;
|
218
|
-
VALUE vdbname;
|
219
|
-
VALUE vmode;
|
220
494
|
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
221
|
-
sword rv;
|
222
|
-
enum logon_type_t logon_type = T_IMPLICIT;
|
223
|
-
ub4 cred = OCI_CRED_RDBMS;
|
224
|
-
ub4 mode = OCI_DEFAULT;
|
225
|
-
OCISvcCtx *svchp = NULL;
|
226
495
|
|
227
|
-
svcctx->
|
228
|
-
|
229
|
-
oci8_do_parse_connect_string(argv[0], &vusername, &vpassword, &vdbname, &vmode);
|
230
|
-
} else {
|
231
|
-
rb_scan_args(argc, argv, "22", &vusername, &vpassword, &vdbname, &vmode);
|
496
|
+
if (svcctx->logoff_strategy != &complex_logoff) {
|
497
|
+
rb_raise(rb_eRuntimeError, "Use this method only for the service context handle created by OCI8#server_handle().");
|
232
498
|
}
|
233
|
-
|
234
|
-
|
235
|
-
rb_ivar_set(self, id_at_username, Qnil);
|
236
|
-
if (NIL_P(vusername) && NIL_P(vpassword)) {
|
237
|
-
/* external credential */
|
238
|
-
logon_type = T_EXPLICIT;
|
239
|
-
cred = OCI_CRED_EXT;
|
240
|
-
} else {
|
241
|
-
/* RDBMS credential */
|
242
|
-
OCI8SafeStringValue(vusername); /* 1 */
|
243
|
-
OCI8SafeStringValue(vpassword); /* 2 */
|
244
|
-
}
|
245
|
-
if (!NIL_P(vdbname)) {
|
246
|
-
OCI8SafeStringValue(vdbname); /* 3 */
|
247
|
-
}
|
248
|
-
if (!NIL_P(vmode)) { /* 4 */
|
249
|
-
logon_type = T_EXPLICIT;
|
250
|
-
Check_Type(vmode, T_SYMBOL);
|
251
|
-
if (vmode == sym_SYSDBA) {
|
252
|
-
mode = OCI_SYSDBA;
|
253
|
-
} else if (vmode == sym_SYSOPER) {
|
254
|
-
mode = OCI_SYSOPER;
|
255
|
-
} else {
|
256
|
-
rb_raise(rb_eArgError, "invalid privilege name %s (expect :SYSDBA or :SYSOPER)", rb_id2name(SYM2ID(vmode)));
|
257
|
-
}
|
499
|
+
if (svcctx->state & OCI8_STATE_SESSION_BEGIN_WAS_CALLED) {
|
500
|
+
rb_raise(rb_eRuntimeError, "Could not use this method twice.");
|
258
501
|
}
|
259
|
-
switch (logon_type) {
|
260
|
-
case T_IMPLICIT:
|
261
|
-
rv = OCILogon_nb(svcctx, oci8_envhp, oci8_errhp, &svchp,
|
262
|
-
RSTRING_ORATEXT(vusername), RSTRING_LEN(vusername),
|
263
|
-
RSTRING_ORATEXT(vpassword), RSTRING_LEN(vpassword),
|
264
|
-
NIL_P(vdbname) ? NULL : RSTRING_ORATEXT(vdbname),
|
265
|
-
NIL_P(vdbname) ? 0 : RSTRING_LEN(vdbname));
|
266
|
-
if (IS_OCI_ERROR(rv)) {
|
267
|
-
oci8_raise(oci8_errhp, rv, NULL);
|
268
|
-
}
|
269
|
-
svcctx->base.hp.svc = svchp;
|
270
|
-
svcctx->base.type = OCI_HTYPE_SVCCTX;
|
271
|
-
svcctx->logon_type = T_IMPLICIT;
|
272
|
-
break;
|
273
|
-
case T_EXPLICIT:
|
274
|
-
/* allocate OCI handles. */
|
275
|
-
rv = OCIHandleAlloc(oci8_envhp, &svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, 0, 0);
|
276
|
-
if (rv != OCI_SUCCESS)
|
277
|
-
oci8_env_raise(oci8_envhp, rv);
|
278
|
-
svcctx->base.type = OCI_HTYPE_SVCCTX;
|
279
|
-
rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->authhp, OCI_HTYPE_SESSION, 0, 0);
|
280
|
-
if (rv != OCI_SUCCESS)
|
281
|
-
oci8_env_raise(oci8_envhp, rv);
|
282
|
-
rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0);
|
283
|
-
if (rv != OCI_SUCCESS)
|
284
|
-
oci8_env_raise(oci8_envhp, rv);
|
285
|
-
|
286
|
-
/* set username and password to OCISession. */
|
287
|
-
if (cred == OCI_CRED_RDBMS) {
|
288
|
-
oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
|
289
|
-
RSTRING_PTR(vusername), RSTRING_LEN(vusername),
|
290
|
-
OCI_ATTR_USERNAME, oci8_errhp));
|
291
|
-
oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
|
292
|
-
RSTRING_PTR(vpassword), RSTRING_LEN(vpassword),
|
293
|
-
OCI_ATTR_PASSWORD, oci8_errhp));
|
294
|
-
}
|
295
502
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
break;
|
311
|
-
default:
|
312
|
-
break;
|
313
|
-
}
|
314
|
-
svcctx->pid = getpid();
|
315
|
-
svcctx->is_autocommit = 0;
|
316
|
-
#ifdef HAVE_RB_THREAD_BLOCKING_REGION
|
317
|
-
svcctx->non_blocking = 1;
|
318
|
-
#endif
|
319
|
-
svcctx->long_read_len = INT2FIX(65535);
|
503
|
+
/* check arguments */
|
504
|
+
Check_Type(cred, T_FIXNUM);
|
505
|
+
Check_Type(mode, T_FIXNUM);
|
506
|
+
|
507
|
+
/* begin session */
|
508
|
+
chker2(OCISessionBegin_nb(svcctx, svcctx->base.hp.ptr, oci8_errhp,
|
509
|
+
svcctx->usrhp, FIX2UINT(cred),
|
510
|
+
FIX2UINT(mode)),
|
511
|
+
&svcctx->base);
|
512
|
+
chker2(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX,
|
513
|
+
svcctx->usrhp, 0, OCI_ATTR_SESSION,
|
514
|
+
oci8_errhp),
|
515
|
+
&svcctx->base);
|
516
|
+
svcctx->state |= OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
|
320
517
|
return Qnil;
|
321
518
|
}
|
322
519
|
|
323
|
-
|
324
520
|
/*
|
325
521
|
* call-seq:
|
326
522
|
* logoff
|
@@ -331,54 +527,20 @@ static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
|
|
331
527
|
static VALUE oci8_svcctx_logoff(VALUE self)
|
332
528
|
{
|
333
529
|
oci8_svcctx_t *svcctx = (oci8_svcctx_t *)DATA_PTR(self);
|
334
|
-
sword rv;
|
335
530
|
|
336
531
|
while (svcctx->base.children != NULL) {
|
337
532
|
oci8_base_free(svcctx->base.children);
|
338
533
|
}
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
rv = OCILogoff_nb(svcctx, svcctx->base.hp.svc, oci8_errhp);
|
534
|
+
if (svcctx->logoff_strategy != NULL) {
|
535
|
+
const oci8_logoff_strategy_t *strategy = svcctx->logoff_strategy;
|
536
|
+
void *data = strategy->prepare(svcctx);
|
343
537
|
svcctx->base.type = 0;
|
344
|
-
svcctx->
|
345
|
-
|
346
|
-
oci8_raise(oci8_errhp, rv, NULL);
|
347
|
-
svcctx->authhp = NULL;
|
348
|
-
svcctx->srvhp = NULL;
|
349
|
-
break;
|
350
|
-
case T_EXPLICIT:
|
351
|
-
oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
|
352
|
-
rv = OCISessionEnd_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, svcctx->authhp, OCI_DEFAULT);
|
353
|
-
if (rv == OCI_SUCCESS) {
|
354
|
-
rv = OCIServerDetach_nb(svcctx, svcctx->srvhp, oci8_errhp, OCI_DEFAULT);
|
355
|
-
}
|
356
|
-
svcctx->logon_type = T_NOT_LOGIN;
|
357
|
-
if (rv != OCI_SUCCESS)
|
358
|
-
oci8_raise(oci8_errhp, rv, NULL);
|
359
|
-
break;
|
360
|
-
case T_NOT_LOGIN:
|
361
|
-
break;
|
538
|
+
svcctx->logoff_strategy = NULL;
|
539
|
+
chker2(oci8_blocking_region(svcctx, strategy->execute, data), &svcctx->base);
|
362
540
|
}
|
363
541
|
return Qtrue;
|
364
542
|
}
|
365
543
|
|
366
|
-
/*
|
367
|
-
* call-seq:
|
368
|
-
* parse(sql_text) -> an instance of OCI8::Cursor
|
369
|
-
*
|
370
|
-
* Prepares the SQL statement and returns a new OCI8::Cursor.
|
371
|
-
*/
|
372
|
-
static VALUE oci8_svcctx_parse(VALUE self, VALUE sql)
|
373
|
-
{
|
374
|
-
VALUE obj = rb_funcall(cOCIStmt, oci8_id_new, 2, self, sql);
|
375
|
-
VALUE prefetch_rows = rb_ivar_get(self, id_at_prefetch_rows);
|
376
|
-
if (!NIL_P(prefetch_rows)) {
|
377
|
-
rb_funcall(obj, id_set_prefetch_rows, 1, prefetch_rows);
|
378
|
-
}
|
379
|
-
return obj;
|
380
|
-
}
|
381
|
-
|
382
544
|
/*
|
383
545
|
* call-seq:
|
384
546
|
* commit
|
@@ -388,7 +550,7 @@ static VALUE oci8_svcctx_parse(VALUE self, VALUE sql)
|
|
388
550
|
static VALUE oci8_commit(VALUE self)
|
389
551
|
{
|
390
552
|
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
391
|
-
|
553
|
+
chker2(OCITransCommit_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT), &svcctx->base);
|
392
554
|
return self;
|
393
555
|
}
|
394
556
|
|
@@ -401,7 +563,7 @@ static VALUE oci8_commit(VALUE self)
|
|
401
563
|
static VALUE oci8_rollback(VALUE self)
|
402
564
|
{
|
403
565
|
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
404
|
-
|
566
|
+
chker2(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT), &svcctx->base);
|
405
567
|
return self;
|
406
568
|
}
|
407
569
|
|
@@ -422,10 +584,7 @@ static VALUE oci8_non_blocking_p(VALUE self)
|
|
422
584
|
#else
|
423
585
|
sb1 non_blocking;
|
424
586
|
|
425
|
-
|
426
|
-
oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp));
|
427
|
-
}
|
428
|
-
oci_lc(OCIAttrGet(svcctx->srvhp, OCI_HTYPE_SERVER, &non_blocking, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp));
|
587
|
+
chker2(OCIAttrGet(svcctx->srvhp, OCI_HTYPE_SERVER, &non_blocking, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp), &svcctx->base);
|
429
588
|
return non_blocking ? Qtrue : Qfalse;
|
430
589
|
#endif
|
431
590
|
}
|
@@ -475,13 +634,13 @@ static VALUE oci8_set_non_blocking(VALUE self, VALUE val)
|
|
475
634
|
#else
|
476
635
|
sb1 non_blocking;
|
477
636
|
|
478
|
-
if (svcctx->
|
479
|
-
|
637
|
+
if (svcctx->state & OCI8_STATE_CPOOL) {
|
638
|
+
rb_raise(rb_eRuntimeError, "Could not set non-blocking mode to a connection allocated from OCI8::ConnectionPool.");
|
480
639
|
}
|
481
|
-
|
640
|
+
chker2(OCIAttrGet(svcctx->srvhp, OCI_HTYPE_SERVER, &non_blocking, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp), &svcctx->base);
|
482
641
|
if ((RTEST(val) && !non_blocking) || (!RTEST(val) && non_blocking)) {
|
483
642
|
/* toggle blocking / non-blocking. */
|
484
|
-
|
643
|
+
chker2(OCIAttrSet(svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0, OCI_ATTR_NONBLOCKING_MODE, oci8_errhp), &svcctx->base);
|
485
644
|
}
|
486
645
|
#endif
|
487
646
|
return val;
|
@@ -560,17 +719,12 @@ static VALUE oci8_set_long_read_len(VALUE self, VALUE val)
|
|
560
719
|
static VALUE oci8_break(VALUE self)
|
561
720
|
{
|
562
721
|
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
563
|
-
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
564
|
-
sword rv;
|
565
|
-
#endif
|
566
722
|
|
567
723
|
if (NIL_P(svcctx->executing_thread)) {
|
568
724
|
return Qfalse;
|
569
725
|
}
|
570
726
|
#ifndef HAVE_RB_THREAD_BLOCKING_REGION
|
571
|
-
|
572
|
-
if (rv != OCI_SUCCESS)
|
573
|
-
oci8_raise(oci8_errhp, rv, NULL);
|
727
|
+
chker2(OCIBreak(svcctx->base.hp.ptr, oci8_errhp), &svcctx->base);
|
574
728
|
#endif
|
575
729
|
rb_thread_wakeup(svcctx->executing_thread);
|
576
730
|
return Qtrue;
|
@@ -608,26 +762,9 @@ static VALUE oci8_oracle_server_vernum(VALUE self)
|
|
608
762
|
oci8_svcctx_t *svcctx = DATA_PTR(self);
|
609
763
|
char buf[100];
|
610
764
|
ub4 version;
|
611
|
-
char *p;
|
612
765
|
|
613
|
-
|
614
|
-
|
615
|
-
oci_lc(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type, &version));
|
616
|
-
return UINT2NUM(version);
|
617
|
-
} else {
|
618
|
-
/* Oracle 8.x */
|
619
|
-
oci_lc(OCIServerVersion(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type));
|
620
|
-
if ((p = strchr(buf, '.')) != NULL) {
|
621
|
-
unsigned int major, minor, update, patch, port_update;
|
622
|
-
while (p >= buf && *p != ' ') {
|
623
|
-
p--;
|
624
|
-
}
|
625
|
-
if (sscanf(p + 1, "%u.%u.%u.%u.%u", &major, &minor, &update, &patch, &port_update) == 5) {
|
626
|
-
return INT2FIX(ORAVERNUM(major, minor, update, patch, port_update));
|
627
|
-
}
|
628
|
-
}
|
629
|
-
return Qnil;
|
630
|
-
}
|
766
|
+
chker2(OCIServerRelease(svcctx->base.hp.ptr, oci8_errhp, (text*)buf, sizeof(buf), (ub1)svcctx->base.type, &version), &svcctx->base);
|
767
|
+
return UINT2NUM(version);
|
631
768
|
}
|
632
769
|
|
633
770
|
/*
|
@@ -693,9 +830,8 @@ static VALUE oci8_ping(VALUE self)
|
|
693
830
|
*/
|
694
831
|
static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
695
832
|
{
|
696
|
-
char *ptr;
|
833
|
+
const char *ptr;
|
697
834
|
ub4 size;
|
698
|
-
int use_attr_set = 1;
|
699
835
|
|
700
836
|
if (!NIL_P(val)) {
|
701
837
|
OCI8SafeStringValue(val);
|
@@ -706,24 +842,19 @@ static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
|
706
842
|
size = 0;
|
707
843
|
}
|
708
844
|
|
709
|
-
if (oracle_client_version
|
710
|
-
use_attr_set = 0;
|
711
|
-
} else if (oracle_client_version < ORAVERNUM(9, 2, 0, 3, 0) && size == 0) {
|
712
|
-
/* Workaround for Bug 2449486 */
|
713
|
-
use_attr_set = 0;
|
714
|
-
}
|
715
|
-
|
716
|
-
if (use_attr_set) {
|
845
|
+
if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0) || size > 0) {
|
717
846
|
if (size > 0 && ptr[0] == ':') {
|
718
847
|
rb_raise(rb_eArgError, "client identifier should not start with ':'.");
|
719
848
|
}
|
720
|
-
|
721
|
-
size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp)
|
849
|
+
chker2(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, (dvoid*)ptr,
|
850
|
+
size, OCI_ATTR_CLIENT_IDENTIFIER, oci8_errhp),
|
851
|
+
DATA_PTR(self));
|
722
852
|
} else {
|
853
|
+
/* Workaround for Bug 2449486 */
|
723
854
|
oci8_exec_sql_var_t bind_vars[1];
|
724
855
|
|
725
856
|
/* :client_id */
|
726
|
-
bind_vars[0].valuep = ptr;
|
857
|
+
bind_vars[0].valuep = (dvoid*)ptr;
|
727
858
|
bind_vars[0].value_sz = size;
|
728
859
|
bind_vars[0].dty = SQLT_CHR;
|
729
860
|
bind_vars[0].indp = NULL;
|
@@ -773,7 +904,7 @@ static VALUE oci8_set_client_identifier(VALUE self, VALUE val)
|
|
773
904
|
*/
|
774
905
|
static VALUE oci8_set_module(VALUE self, VALUE val)
|
775
906
|
{
|
776
|
-
char *ptr;
|
907
|
+
const char *ptr;
|
777
908
|
ub4 size;
|
778
909
|
|
779
910
|
if (!NIL_P(val)) {
|
@@ -786,14 +917,15 @@ static VALUE oci8_set_module(VALUE self, VALUE val)
|
|
786
917
|
}
|
787
918
|
if (oracle_client_version >= ORAVER_10_1) {
|
788
919
|
/* Oracle 10g or upper */
|
789
|
-
|
790
|
-
size, OCI_ATTR_MODULE, oci8_errhp)
|
920
|
+
chker2(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, (dvoid*)ptr,
|
921
|
+
size, OCI_ATTR_MODULE, oci8_errhp),
|
922
|
+
DATA_PTR(self));
|
791
923
|
} else {
|
792
924
|
/* Oracle 9i or lower */
|
793
925
|
oci8_exec_sql_var_t bind_vars[1];
|
794
926
|
|
795
927
|
/* :module */
|
796
|
-
bind_vars[0].valuep = ptr;
|
928
|
+
bind_vars[0].valuep = (dvoid*)ptr;
|
797
929
|
bind_vars[0].value_sz = size;
|
798
930
|
bind_vars[0].dty = SQLT_CHR;
|
799
931
|
bind_vars[0].indp = NULL;
|
@@ -842,7 +974,7 @@ static VALUE oci8_set_module(VALUE self, VALUE val)
|
|
842
974
|
*/
|
843
975
|
static VALUE oci8_set_action(VALUE self, VALUE val)
|
844
976
|
{
|
845
|
-
char *ptr;
|
977
|
+
const char *ptr;
|
846
978
|
ub4 size;
|
847
979
|
|
848
980
|
if (!NIL_P(val)) {
|
@@ -855,14 +987,15 @@ static VALUE oci8_set_action(VALUE self, VALUE val)
|
|
855
987
|
}
|
856
988
|
if (oracle_client_version >= ORAVER_10_1) {
|
857
989
|
/* Oracle 10g or upper */
|
858
|
-
|
859
|
-
size, OCI_ATTR_ACTION, oci8_errhp)
|
990
|
+
chker2(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, (dvoid*)ptr,
|
991
|
+
size, OCI_ATTR_ACTION, oci8_errhp),
|
992
|
+
DATA_PTR(self));
|
860
993
|
} else {
|
861
994
|
/* Oracle 9i or lower */
|
862
995
|
oci8_exec_sql_var_t bind_vars[1];
|
863
996
|
|
864
997
|
/* :action */
|
865
|
-
bind_vars[0].valuep = ptr;
|
998
|
+
bind_vars[0].valuep = (dvoid*)ptr;
|
866
999
|
bind_vars[0].value_sz = size;
|
867
1000
|
bind_vars[0].dty = SQLT_CHR;
|
868
1001
|
bind_vars[0].indp = NULL;
|
@@ -904,7 +1037,7 @@ static VALUE oci8_set_action(VALUE self, VALUE val)
|
|
904
1037
|
*/
|
905
1038
|
static VALUE oci8_set_client_info(VALUE self, VALUE val)
|
906
1039
|
{
|
907
|
-
char *ptr;
|
1040
|
+
const char *ptr;
|
908
1041
|
ub4 size;
|
909
1042
|
|
910
1043
|
if (!NIL_P(val)) {
|
@@ -917,14 +1050,15 @@ static VALUE oci8_set_client_info(VALUE self, VALUE val)
|
|
917
1050
|
}
|
918
1051
|
if (oracle_client_version >= ORAVER_10_1) {
|
919
1052
|
/* Oracle 10g or upper */
|
920
|
-
|
921
|
-
size, OCI_ATTR_CLIENT_INFO, oci8_errhp)
|
1053
|
+
chker2(OCIAttrSet(oci8_get_oci_session(self), OCI_HTYPE_SESSION, (dvoid*)ptr,
|
1054
|
+
size, OCI_ATTR_CLIENT_INFO, oci8_errhp),
|
1055
|
+
DATA_PTR(self));
|
922
1056
|
} else {
|
923
1057
|
/* Oracle 9i or lower */
|
924
1058
|
oci8_exec_sql_var_t bind_vars[1];
|
925
1059
|
|
926
1060
|
/* :client_info */
|
927
|
-
bind_vars[0].valuep = ptr;
|
1061
|
+
bind_vars[0].valuep = (dvoid*)ptr;
|
928
1062
|
bind_vars[0].value_sz = size;
|
929
1063
|
bind_vars[0].dty = SQLT_CHR;
|
930
1064
|
bind_vars[0].indp = NULL;
|
@@ -941,14 +1075,14 @@ static VALUE oci8_set_client_info(VALUE self, VALUE val)
|
|
941
1075
|
VALUE Init_oci8(void)
|
942
1076
|
{
|
943
1077
|
#if 0
|
944
|
-
/*
|
945
|
-
* OCIHandle is the abstract base class for all OCI handles and
|
946
|
-
* descriptors which are opaque data types of Oracle Call Interface.
|
947
|
-
*/
|
948
1078
|
oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
|
949
1079
|
cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle);
|
950
1080
|
#endif
|
951
|
-
cOCI8 = oci8_define_class("OCI8", &
|
1081
|
+
cOCI8 = oci8_define_class("OCI8", &oci8_svcctx_vtable);
|
1082
|
+
cSession = oci8_define_class_under(cOCI8, "Session", &oci8_svcctx_associate_vtable);
|
1083
|
+
cServer = oci8_define_class_under(cOCI8, "Server", &oci8_svcctx_associate_vtable);
|
1084
|
+
id_at_session_handle = rb_intern("@session_handle");
|
1085
|
+
id_at_server_handle = rb_intern("@server_handle");
|
952
1086
|
|
953
1087
|
oracle_client_vernum = INT2FIX(oracle_client_version);
|
954
1088
|
if (have_OCIClientVersion) {
|
@@ -957,20 +1091,21 @@ VALUE Init_oci8(void)
|
|
957
1091
|
oracle_client_vernum = INT2FIX(ORAVERNUM(major, minor, update, patch, port_update));
|
958
1092
|
}
|
959
1093
|
|
960
|
-
sym_SYSDBA = ID2SYM(rb_intern("SYSDBA"));
|
961
|
-
sym_SYSOPER = ID2SYM(rb_intern("SYSOPER"));
|
962
1094
|
id_at_prefetch_rows = rb_intern("@prefetch_rows");
|
963
|
-
id_at_username = rb_intern("@username");
|
964
1095
|
id_set_prefetch_rows = rb_intern("prefetch_rows=");
|
965
1096
|
|
1097
|
+
rb_define_const(cOCI8, "VERSION", rb_obj_freeze(rb_usascii_str_new_cstr(OCI8LIB_VERSION)));
|
966
1098
|
rb_define_singleton_method_nodoc(cOCI8, "oracle_client_vernum", oci8_s_oracle_client_vernum, 0);
|
967
|
-
|
968
|
-
|
969
|
-
}
|
1099
|
+
rb_define_singleton_method_nodoc(cOCI8, "__set_property", oci8_s_set_property, 2);
|
1100
|
+
rb_define_singleton_method(cOCI8, "error_message", oci8_s_error_message, 1);
|
970
1101
|
rb_define_private_method(cOCI8, "parse_connect_string", oci8_parse_connect_string, 1);
|
971
|
-
|
1102
|
+
rb_define_private_method(cOCI8, "logon", oci8_logon, 3);
|
1103
|
+
rb_define_private_method(cOCI8, "allocate_handles", oci8_allocate_handles, 0);
|
1104
|
+
rb_define_private_method(cOCI8, "session_handle", oci8_get_session_handle, 0);
|
1105
|
+
rb_define_private_method(cOCI8, "server_handle", oci8_get_server_handle, 0);
|
1106
|
+
rb_define_private_method(cOCI8, "server_attach", oci8_server_attach, 2);
|
1107
|
+
rb_define_private_method(cOCI8, "session_begin", oci8_session_begin, 2);
|
972
1108
|
rb_define_method(cOCI8, "logoff", oci8_svcctx_logoff, 0);
|
973
|
-
rb_define_method(cOCI8, "parse", oci8_svcctx_parse, 1);
|
974
1109
|
rb_define_method(cOCI8, "commit", oci8_commit, 0);
|
975
1110
|
rb_define_method(cOCI8, "rollback", oci8_rollback, 0);
|
976
1111
|
rb_define_method(cOCI8, "non_blocking?", oci8_non_blocking_p, 0);
|
@@ -987,6 +1122,7 @@ VALUE Init_oci8(void)
|
|
987
1122
|
rb_define_method(cOCI8, "module=", oci8_set_module, 1);
|
988
1123
|
rb_define_method(cOCI8, "action=", oci8_set_action, 1);
|
989
1124
|
rb_define_method(cOCI8, "client_info=", oci8_set_client_info, 1);
|
1125
|
+
rb_define_attr(cOCI8, "last_error", 1, 1);
|
990
1126
|
return cOCI8;
|
991
1127
|
}
|
992
1128
|
|
@@ -1004,11 +1140,7 @@ OCISvcCtx *oci8_get_oci_svcctx(VALUE obj)
|
|
1004
1140
|
OCISession *oci8_get_oci_session(VALUE obj)
|
1005
1141
|
{
|
1006
1142
|
oci8_svcctx_t *svcctx = oci8_get_svcctx(obj);
|
1007
|
-
|
1008
|
-
if (svcctx->authhp == NULL) {
|
1009
|
-
oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->authhp, 0, OCI_ATTR_SESSION, oci8_errhp));
|
1010
|
-
}
|
1011
|
-
return svcctx->authhp;
|
1143
|
+
return svcctx->usrhp;
|
1012
1144
|
}
|
1013
1145
|
|
1014
1146
|
void oci8_check_pid_consistency(oci8_svcctx_t *svcctx)
|