ruby-oci8 1.0.7 → 2.0.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.
Files changed (89) hide show
  1. data/ChangeLog +1254 -390
  2. data/Makefile +10 -13
  3. data/README +56 -385
  4. data/VERSION +1 -1
  5. data/dist-files +26 -27
  6. data/ext/oci8/.document +1 -0
  7. data/ext/oci8/MANIFEST +0 -4
  8. data/ext/oci8/apiwrap.c.tmpl +172 -0
  9. data/ext/oci8/apiwrap.h.tmpl +61 -0
  10. data/ext/oci8/apiwrap.rb +91 -0
  11. data/ext/oci8/apiwrap.yml +1243 -0
  12. data/ext/oci8/attr.c +124 -384
  13. data/ext/oci8/bind.c +472 -164
  14. data/ext/oci8/encoding.c +196 -0
  15. data/ext/oci8/env.c +84 -253
  16. data/ext/oci8/error.c +196 -127
  17. data/ext/oci8/extconf.rb +82 -59
  18. data/ext/oci8/lob.c +710 -370
  19. data/ext/oci8/metadata.c +359 -0
  20. data/ext/oci8/object.c +622 -0
  21. data/ext/oci8/oci8.c +577 -161
  22. data/ext/oci8/oci8.h +354 -258
  23. data/ext/oci8/oci8lib.c +493 -0
  24. data/ext/oci8/ocidatetime.c +473 -0
  25. data/ext/oci8/ocinumber.c +1123 -24
  26. data/ext/oci8/oraconf.rb +72 -106
  27. data/ext/oci8/oradate.c +511 -321
  28. data/ext/oci8/stmt.c +752 -572
  29. data/ext/oci8/win32.c +131 -0
  30. data/ext/oci8/xmldb.c +383 -0
  31. data/lib/.document +2 -0
  32. data/lib/dbd/OCI8.rb +2 -17
  33. data/lib/oci8.rb.in +41 -1622
  34. data/lib/oci8/.document +5 -0
  35. data/lib/oci8/compat.rb +108 -0
  36. data/lib/oci8/datetime.rb +489 -0
  37. data/lib/oci8/encoding-init.rb +40 -0
  38. data/lib/oci8/encoding.yml +537 -0
  39. data/lib/oci8/metadata.rb +2077 -0
  40. data/lib/oci8/object.rb +548 -0
  41. data/lib/oci8/oci8.rb +773 -0
  42. data/lib/oci8/oracle_version.rb +144 -0
  43. data/metaconfig +3 -3
  44. data/ruby-oci8.gemspec +5 -5
  45. data/setup.rb +4 -4
  46. data/test/config.rb +64 -84
  47. data/test/test_all.rb +14 -21
  48. data/test/test_array_dml.rb +317 -0
  49. data/test/test_bind_raw.rb +18 -25
  50. data/test/test_bind_time.rb +78 -91
  51. data/test/test_break.rb +37 -35
  52. data/test/test_clob.rb +33 -89
  53. data/test/test_connstr.rb +5 -4
  54. data/test/test_datetime.rb +469 -0
  55. data/test/test_dbi.rb +99 -60
  56. data/test/test_dbi_clob.rb +3 -8
  57. data/test/test_metadata.rb +65 -51
  58. data/test/test_oci8.rb +151 -55
  59. data/test/test_oracle_version.rb +70 -0
  60. data/test/test_oradate.rb +76 -83
  61. data/test/test_oranumber.rb +405 -71
  62. data/test/test_rowid.rb +6 -11
  63. metadata +31 -32
  64. data/NEWS +0 -420
  65. data/ext/oci8/const.c +0 -165
  66. data/ext/oci8/define.c +0 -53
  67. data/ext/oci8/describe.c +0 -81
  68. data/ext/oci8/descriptor.c +0 -39
  69. data/ext/oci8/handle.c +0 -273
  70. data/ext/oci8/oranumber.c +0 -445
  71. data/ext/oci8/param.c +0 -37
  72. data/ext/oci8/server.c +0 -182
  73. data/ext/oci8/session.c +0 -99
  74. data/ext/oci8/svcctx.c +0 -238
  75. data/ruby-oci8.spec +0 -62
  76. data/support/README +0 -4
  77. data/support/runit/assert.rb +0 -281
  78. data/support/runit/cui/testrunner.rb +0 -101
  79. data/support/runit/error.rb +0 -4
  80. data/support/runit/method_mappable.rb +0 -20
  81. data/support/runit/robserver.rb +0 -25
  82. data/support/runit/setuppable.rb +0 -15
  83. data/support/runit/teardownable.rb +0 -16
  84. data/support/runit/testcase.rb +0 -113
  85. data/support/runit/testfailure.rb +0 -25
  86. data/support/runit/testresult.rb +0 -121
  87. data/support/runit/testsuite.rb +0 -43
  88. data/support/runit/version.rb +0 -3
  89. data/test/test_describe.rb +0 -137
@@ -0,0 +1,196 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * encoding.c - part of ruby-oci8
4
+ *
5
+ * Copyright (C) 2008 KUBO Takehiro <kubo@jiubao.org>
6
+ *
7
+ */
8
+ #include "oci8.h"
9
+
10
+ #ifndef OCI_NLS_MAXBUFSZ
11
+ #define OCI_NLS_MAXBUFSZ 100
12
+ #endif
13
+
14
+ /* type of callback function's argument */
15
+ typedef struct {
16
+ oci8_svcctx_t *svcctx;
17
+ OCIStmt *stmtp;
18
+ union {
19
+ VALUE name;
20
+ int csid;
21
+ } u;
22
+ } cb_arg_t;
23
+
24
+ /* Oracle charset id -> Oracle charset name */
25
+ static VALUE csid2name;
26
+
27
+ /* Oracle charset name -> Oracle charset id */
28
+ static ID id_upcase;
29
+ static VALUE csname2id;
30
+ static VALUE oci8_charset_name2id(VALUE svc, VALUE name);
31
+ #ifdef HAVE_TYPE_RB_ENCODING
32
+ rb_encoding *oci8_encoding;
33
+ #endif
34
+
35
+ VALUE oci8_charset_id2name(VALUE svc, VALUE csid)
36
+ {
37
+ VALUE name = rb_hash_aref(csid2name, csid);
38
+
39
+ if (!NIL_P(name)) {
40
+ return name;
41
+ }
42
+ Check_Type(csid, T_FIXNUM);
43
+ if (have_OCINlsCharSetIdToName) {
44
+ /* Oracle 9iR2 or upper */
45
+ char buf[OCI_NLS_MAXBUFSZ];
46
+ sword rv;
47
+
48
+ rv = OCINlsCharSetIdToName(oci8_envhp, TO_ORATEXT(buf), sizeof(buf), FIX2INT(csid));
49
+ if (rv != OCI_SUCCESS) {
50
+ return Qnil;
51
+ }
52
+ name = rb_usascii_str_new_cstr(buf);
53
+ } else {
54
+ /* Oracle 9iR1 or lower */
55
+ oci8_exec_sql_var_t bind_vars[2];
56
+ char buf[OCI_NLS_MAXBUFSZ];
57
+ ub2 buflen = 0;
58
+ int ival = FIX2INT(csid);
59
+
60
+ /* :name */
61
+ bind_vars[0].valuep = buf;
62
+ bind_vars[0].value_sz = OCI_NLS_MAXBUFSZ;
63
+ bind_vars[0].dty = SQLT_CHR;
64
+ bind_vars[0].indp = NULL;
65
+ bind_vars[0].alenp = &buflen;
66
+ /* :csid */
67
+ bind_vars[1].valuep = &ival;
68
+ bind_vars[1].value_sz = sizeof(int);
69
+ bind_vars[1].dty = SQLT_INT;
70
+ bind_vars[1].indp = NULL;
71
+ bind_vars[1].alenp = NULL;
72
+
73
+ /* convert chaset id to charset name by querying Oracle server. */
74
+ oci8_exec_sql(oci8_get_svcctx(svc), "BEGIN :name := nls_charset_name(:csid); END;", 0, NULL, 2, bind_vars, 1);
75
+ if (buflen == 0) {
76
+ return Qnil;
77
+ }
78
+ name = rb_usascii_str_new(buf, buflen);
79
+ }
80
+ OBJ_FREEZE(name);
81
+ rb_hash_aset(csid2name, csid, name);
82
+ rb_hash_aset(csname2id, name, csid);
83
+ return name;
84
+ }
85
+
86
+ static VALUE oci8_charset_name2id(VALUE svc, VALUE name)
87
+ {
88
+ VALUE csid;
89
+
90
+ name = rb_funcall(name, id_upcase, 0);
91
+ csid = rb_hash_aref(csname2id, StringValue(name));
92
+ if (!NIL_P(csid)) {
93
+ return csid;
94
+ }
95
+ if (have_OCINlsCharSetNameToId) {
96
+ /* Oracle 9iR2 or upper */
97
+ ub2 rv;
98
+
99
+ rv = OCINlsCharSetNameToId(oci8_envhp, RSTRING_ORATEXT(name));
100
+ if (rv == 0) {
101
+ return Qnil;
102
+ }
103
+ csid = INT2FIX(rv);
104
+ } else {
105
+ /* Oracle 9iR1 or lower */
106
+ oci8_exec_sql_var_t bind_vars[2];
107
+ int ival;
108
+ sb2 ind = 0; /* null indicator */
109
+
110
+ /* :csid */
111
+ bind_vars[0].valuep = &ival;
112
+ bind_vars[0].value_sz = sizeof(int);
113
+ bind_vars[0].dty = SQLT_INT;
114
+ bind_vars[0].indp = &ind;
115
+ bind_vars[0].alenp = NULL;
116
+ /* :name */
117
+ bind_vars[1].valuep = RSTRING_PTR(name);
118
+ bind_vars[1].value_sz = RSTRING_LEN(name);
119
+ bind_vars[1].dty = SQLT_CHR;
120
+ bind_vars[1].indp = NULL;
121
+ bind_vars[1].alenp = NULL;
122
+
123
+ /* convert chaset name to charset id by querying Oracle server. */
124
+ oci8_exec_sql(oci8_get_svcctx(svc), "BEGIN :csid := nls_charset_id(:name); END;", 0, NULL, 2, bind_vars, 1);
125
+ if (ind) {
126
+ return Qnil;
127
+ }
128
+ csid = INT2FIX(ival);
129
+ }
130
+ rb_hash_aset(csid2name, csid, name);
131
+ rb_hash_aset(csname2id, name, csid);
132
+ return csid;
133
+ }
134
+
135
+ #ifdef HAVE_TYPE_RB_ENCODING
136
+
137
+ /*
138
+ * call-seq:
139
+ * OCI8.encoding -> enc
140
+ *
141
+ * (new in ruby 1.9)
142
+ *
143
+ * Returns Oracle client encoding.
144
+ *
145
+ * String values passed to Oracle, such as SQL statements,
146
+ * bind values etc., are converted from their encoding to
147
+ * the Oracle client encoding.
148
+ *
149
+ * If <code>Encoding.default_internal</code> is nil,
150
+ * string values got from Oracle are tagged by
151
+ * <code>OCI8.encoding</code>. If not nil, they are
152
+ * converted from <code>OCI8.encoding</code> to
153
+ * <code>Encoding.default_internal</code> by default.
154
+ *
155
+ * If it is 'ASCII-8BIT', no encoding conversions are done.
156
+ */
157
+ static VALUE oci8_get_encoding(VALUE klass)
158
+ {
159
+ return rb_enc_from_encoding(oci8_encoding);
160
+ }
161
+
162
+ /*
163
+ * call-seq:
164
+ * OCI8.encoding = enc or nil
165
+ *
166
+ * (new in ruby 1.9)
167
+ *
168
+ * Sets Oracle client encoding.
169
+ */
170
+ static VALUE oci8_set_encoding(VALUE klass, VALUE encoding)
171
+ {
172
+ if (NIL_P(encoding)) {
173
+ oci8_encoding = NULL;
174
+ } else {
175
+ oci8_encoding = rb_to_encoding(encoding);
176
+ }
177
+ return encoding;
178
+ }
179
+ #endif
180
+
181
+ void Init_oci8_encoding(VALUE cOCI8)
182
+ {
183
+ csid2name = rb_hash_new();
184
+ rb_global_variable(&csid2name);
185
+
186
+ id_upcase = rb_intern("upcase");
187
+ csname2id = rb_hash_new();
188
+ rb_global_variable(&csname2id);
189
+
190
+ rb_define_method(cOCI8, "charset_name2id", oci8_charset_name2id, 1);
191
+ rb_define_method(cOCI8, "charset_id2name", oci8_charset_id2name, 1);
192
+ #ifdef HAVE_TYPE_RB_ENCODING
193
+ rb_define_singleton_method(cOCI8, "encoding", oci8_get_encoding, 0);
194
+ rb_define_singleton_method(cOCI8, "encoding=", oci8_set_encoding, 1);
195
+ #endif
196
+ }
@@ -1,276 +1,107 @@
1
+ /* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
1
2
  /*
2
3
  env.c - part of ruby-oci8
3
4
 
4
- Copyright (C) 2002 KUBO Takehiro <kubo@jiubao.org>
5
+ Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
5
6
 
6
- =begin
7
- == OCIEnv
8
- The environment handle is the source of all OCI objects.
9
- Usually there is one instance per one application.
10
-
11
- super class: ((<OCIHandle>))
12
-
13
- correspond native OCI datatype: ((|OCIEnv|))
14
- =end
15
7
  */
16
8
  #include "oci8.h"
17
- #include <util.h> /* ruby_setenv */
18
-
19
- RBOCI_NORETURN(static void oci8_raise_init_error(void));
20
-
21
- static void oci8_raise_init_error(void)
22
- {
23
- VALUE msg = rb_str_new2("OCI Library Initialization Error");
24
- VALUE exc = rb_funcall(eOCIError, oci8_id_new, 1, msg);
25
- rb_ivar_set(exc, oci8_id_code, rb_ary_new3(1, INT2FIX(-1)));
26
- rb_ivar_set(exc, oci8_id_message, rb_ary_new3(1, msg));
27
- rb_exc_raise(exc);
28
- }
29
-
30
- static VALUE oci8_env_s_initialize(int argc, VALUE *argv, VALUE klass)
31
- {
32
- VALUE vmode;
33
- ub4 mode;
34
- sword rv;
35
-
36
- #ifndef WIN32
37
- /* workaround code.
38
- *
39
- * Some instant clients set the environment variables
40
- * ORA_NLS_PROFILE33, ORA_NLS10 and ORACLE_HOME if they aren't
41
- * set. It causes problems on some platforms.
42
- */
43
- if (RTEST(rb_eval_string("RUBY_VERSION == \"1.8.4\""))) {
44
- if (getenv("ORA_NLS_PROFILE33") == NULL) {
45
- ruby_setenv("ORA_NLS_PROFILE33", "");
46
- }
47
- if (getenv("ORA_NLS10") == NULL) {
48
- ruby_setenv("ORA_NLS10", "");
49
- }
50
- if (getenv("ORACLE_HOME") == NULL) {
51
- ruby_setenv("ORACLE_HOME", ".");
52
- }
53
- }
54
- #endif /* WIN32 */
55
-
56
- rb_scan_args(argc, argv, "01", &vmode);
57
- Get_Int_With_Default(argc, 1, vmode, mode, OCI_DEFAULT); /* 1 */
58
-
59
- rv = OCIInitialize(mode, NULL, NULL, NULL, NULL);
60
- return INT2FIX(rv);
61
- }
62
-
63
- static VALUE oci8_env_s_init(int argc, VALUE *argv, VALUE klass)
64
- {
65
- VALUE vmode;
66
- ub4 mode;
67
- OCIEnv *envhp = NULL;
68
- OCIError *errhp;
69
- oci8_handle_t *h;
70
- sword rv;
71
-
72
- rb_scan_args(argc, argv, "01", &vmode);
73
- Get_Int_With_Default(argc, 1, vmode, mode, OCI_DEFAULT); /* 1 */
74
-
75
- rv = OCIEnvInit(&envhp, OCI_DEFAULT, 0, NULL);
76
- if (envhp == NULL) {
77
- oci8_raise_init_error();
78
- }
79
- if (rv != OCI_SUCCESS)
80
- oci8_env_raise(envhp, rv);
81
- rv = OCIHandleAlloc(envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
82
- if (rv != OCI_SUCCESS)
83
- oci8_env_raise(envhp, rv);
84
- h = oci8_make_handle(OCI_HTYPE_ENV, envhp, errhp, NULL, 0);
85
- return h->self;
86
- }
87
-
88
- /*
89
- =begin
90
- --- OCIEnv.create([mode])
91
- create the environment handle. Don't call `new'.
92
-
93
- :mode
94
- ((|OCI_DEFAULT|)), ((|OCI_THREADED|)), ((|OCI_OBJECT|)), ((|OCI_SHARED|))
95
- or these combination.
96
- But I test only ((|OCI_DEFAULT|)). Default value is ((|OCI_DEFAULT|)).
97
-
98
- ((|OCI_THREADED|)): if your application use native thread(not ruby's thread), use this.
99
-
100
- ((|OCI_OBJECT|)): for OCI objects. But current implementation doesn't support OCI Object-Relational functions.
101
- This is for ((*far future*)) extension, because my plan doesn't include `OCI object support'.
102
-
103
- ((|OCI_SHARED|))(Oracle 8i or later): for ((<Shared Data Mode>)).
104
-
105
- :return value
106
- A instance of ((<OCIEnv>)).
107
-
108
- correspond native OCI function: ((|OCIEnvCreate|)) (if ((|OCIEnvCreate|)) is not found, the combination of ((|OCIInitialize|)) and ((|OCIEnvInit|)).)
109
- =end
110
- */
111
- #ifdef HAVE_OCIENVCREATE
112
- static VALUE oci8_env_s_create(int argc, VALUE *argv, VALUE klass)
113
- {
114
- VALUE vmode;
115
- ub4 mode;
116
- OCIEnv *envhp = NULL;
117
- OCIError *errhp;
118
- oci8_handle_t *h;
119
- sword rv;
120
9
 
121
- rb_scan_args(argc, argv, "01", &vmode);
122
- Get_Int_With_Default(argc, 1, vmode, mode, OCI_DEFAULT); /* 1 */
123
-
124
- rv = OCIEnvCreate(&envhp, mode, NULL, NULL, NULL, NULL, 0, NULL);
125
- if (envhp == NULL) {
126
- oci8_raise_init_error();
127
- }
128
- if (rv != OCI_SUCCESS)
129
- oci8_env_raise(envhp, rv);
130
- rv = OCIHandleAlloc(envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
131
- if (rv != OCI_SUCCESS)
132
- oci8_env_raise(envhp, rv);
133
- h = oci8_make_handle(OCI_HTYPE_ENV, envhp, errhp, NULL, 0);
134
- return h->self;
135
- }
10
+ #if !defined(RUBY_VM)
11
+ /* ruby_setenv for workaround ruby 1.8.4 */
12
+ #include <util.h>
136
13
  #endif
137
14
 
15
+ OCIEnv *oci8_envhp;
16
+ #ifdef RUBY_VM
138
17
  /*
139
- =begin
140
- --- OCIEnv.terminate([mode])
141
- :mode
142
- ((|OCI_DEFAULT|)) only valid. Default value is ((|OCI__DEFAULT|)).
143
-
144
- correspond native OCI function: ((|OCITerminate|))
145
- =end
146
- */
147
- #ifdef HAVE_OCITERMINATE
148
- static VALUE oci8_env_s_terminate(int argc, VALUE *argv, VALUE klass)
149
- {
150
- VALUE vmode;
151
- ub4 mode;
152
-
153
- if (rb_scan_args(argc, argv, "01", &vmode) == 1) {
154
- Check_Type(vmode, T_FIXNUM);
155
- mode = FIX2INT(vmode);
156
- } else {
157
- mode = OCI_DEFAULT;
158
- }
159
-
160
- OCITerminate(mode);
161
- return Qnil;
162
- }
163
- #endif
18
+ * oci8_errhp is a thread local object in ruby 1.9.
19
+ */
164
20
 
165
- /*
166
- =begin
167
- --- OCIEnv#alloc(handle)
168
- create a new OCI handle.
169
- :handle
170
- The valid values are ((<OCISvcCtx>)), ((<OCIStmt>)),
171
- ((<OCIServer>)), ((<OCISession>)), and ((<OCIDescribe>)).
172
- :return value
173
- A newly created handle.
21
+ oci8_tls_key_t oci8_tls_key; /* native thread key */
22
+ static ID id_thread_key; /* ruby's thread key */
174
23
 
175
- correspond native OCI function: ((|OCIHandleAlloc|))
176
- =end
177
- */
178
- typedef sword (*alloc_func_t)(CONST dvoid *, dvoid **, CONST ub4, CONST size_t, dvoid **);
179
- static VALUE oci8_handle_alloc(VALUE self, VALUE klass)
24
+ static void oci8_free_errhp(OCIError *errhp)
180
25
  {
181
- sword rv;
182
- dvoid *hp;
183
- oci8_handle_t *envh;
184
- oci8_handle_t *h;
185
- int i;
186
- struct {
187
- VALUE *klass;
188
- ub4 type;
189
- alloc_func_t alloc_func;
190
- } alloc_map[] = {
191
- {&cOCISvcCtx, OCI_HTYPE_SVCCTX, (alloc_func_t)OCIHandleAlloc},
192
- {&cOCIStmt, OCI_HTYPE_STMT, (alloc_func_t)OCIHandleAlloc},
193
- {&cOCIServer, OCI_HTYPE_SERVER, (alloc_func_t)OCIHandleAlloc},
194
- {&cOCISession, OCI_HTYPE_SESSION, (alloc_func_t)OCIHandleAlloc},
195
- {&cOCIDescribe, OCI_HTYPE_DESCRIBE, (alloc_func_t)OCIHandleAlloc},
196
- {&cOCILobLocator, OCI_DTYPE_LOB, (alloc_func_t)OCIDescriptorAlloc},
197
- {&cOCIFileLocator, OCI_DTYPE_FILE, (alloc_func_t)OCIDescriptorAlloc},
198
- };
199
- #define ALLOC_MAP_SIZE (sizeof(alloc_map) / sizeof(alloc_map[0]))
200
-
201
- Get_Handle(self, envh);
202
- for (i = 0;i < ALLOC_MAP_SIZE;i++) {
203
- if (alloc_map[i].klass[0] == klass)
204
- break;
205
- }
206
- if (i == ALLOC_MAP_SIZE) {
207
- rb_raise(rb_eTypeError, "not valid handle type %s", rb_class2name(CLASS_OF(klass)));
208
- }
209
-
210
- rv = alloc_map[i].alloc_func(envh->hp, &hp, alloc_map[i].type, 0, NULL);
211
- if (rv != OCI_SUCCESS)
212
- oci8_env_raise(envh->hp, rv);
213
- h = oci8_make_handle(alloc_map[i].type, hp, envh->errhp, envh, 0);
214
- return h->self;
26
+ OCIHandleFree(errhp, OCI_HTYPE_ERROR);
215
27
  }
216
28
 
217
- /*
218
- =begin
219
- --- OCIEnv#logon(username, password, dbname)
220
- Logon to the Oracle server.
221
-
222
- See ((<Simplified Logon>)) and ((<Explicit Attach and Begin Session>))
223
-
224
- :username
225
- the username.
226
- :password
227
- the user's password.
228
- :dbname
229
- the name of the database, or nil.
230
- :return value
231
- A instance of ((<OCISvcCtx>))
232
- For example:
233
- env = OCIEnv.create()
234
- svc = env.logon("SCOTT", "TIGER", nil)
235
- or
236
- svc = env.logon("SCOTT", "TIGER", "ORCL.WORLD")
237
-
238
- correspond native OCI function: ((|OCILogon|))
239
- =end
240
- */
241
- static VALUE oci8_logon(VALUE self, VALUE username, VALUE password, VALUE dbname)
29
+ OCIError *oci8_make_errhp(void)
242
30
  {
243
- oci8_handle_t *envh;
244
- oci8_handle_t *svch;
245
- OCISvcCtx *svchp;
246
- oci8_string_t u, p, d;
247
- VALUE obj;
248
- sword rv;
249
-
250
- Get_Handle(self, envh);
251
- Get_String(username, u);
252
- Get_String(password, p);
253
- Get_String(dbname, d);
254
- rv = OCILogon(envh->hp, envh->errhp, &svchp,
255
- u.ptr, u.len, p.ptr, p.len, d.ptr, d.len);
256
- if (rv != OCI_SUCCESS) {
257
- oci8_raise(envh->errhp, rv, NULL);
258
- }
259
- svch = oci8_make_handle(OCI_HTYPE_SVCCTX, svchp, envh->errhp, envh, 0);
260
- obj = svch->self;
261
- return obj;
31
+ OCIError *errhp;
32
+ VALUE obj;
33
+ sword rv;
34
+
35
+ /* create a new errhp. */
36
+ rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
37
+ if (rv != OCI_SUCCESS) {
38
+ oci8_env_raise(oci8_envhp, rv);
39
+ }
40
+ /* create a new ruby object which contains errhp to make
41
+ * sure that the errhp is freed when it become unnecessary.
42
+ */
43
+ obj = Data_Wrap_Struct(rb_cObject, NULL, oci8_free_errhp, errhp);
44
+ /* set the ruby object to ruby's thread local storage to prevent
45
+ * it from being freed while the thread is available.
46
+ */
47
+ rb_thread_local_aset(rb_thread_current(), id_thread_key, obj);
48
+
49
+ oci8_tls_set(oci8_tls_key, (void*)errhp);
50
+ return errhp;
262
51
  }
52
+ #else
53
+ /*
54
+ * oci8_errhp is global in ruby 1.8.
55
+ */
56
+ OCIError *oci8_errhp;
57
+ #endif
263
58
 
264
59
  void Init_oci8_env(void)
265
60
  {
266
- rb_define_singleton_method(cOCIEnv, "initialise", oci8_env_s_initialize, -1);
267
- rb_define_singleton_method(cOCIEnv, "init", oci8_env_s_init, -1);
268
- #ifdef HAVE_OCIENVCREATE
269
- rb_define_singleton_method(cOCIEnv, "create", oci8_env_s_create, -1);
61
+ sword rv;
62
+ #ifdef RUBY_VM
63
+ ub4 mode = OCI_OBJECT | OCI_THREADED;
64
+ int error;
65
+ #else
66
+ ub4 mode = OCI_OBJECT;
270
67
  #endif
271
- #ifdef HAVE_OCITERMINATE
272
- rb_define_singleton_method(cOCIEnv, "terminate", oci8_env_s_terminate, -1);
68
+
69
+ #if !defined(RUBY_VM) && !defined(_WIN32)
70
+ /* workaround code.
71
+ *
72
+ * Some instant clients set the environment variables
73
+ * ORA_NLS_PROFILE33, ORA_NLS10 and ORACLE_HOME if they aren't
74
+ * set. It causes problems on some platforms.
75
+ */
76
+ if (RTEST(rb_eval_string("RUBY_VERSION == \"1.8.4\""))) {
77
+ if (getenv("ORA_NLS_PROFILE33") == NULL) {
78
+ ruby_setenv("ORA_NLS_PROFILE33", "");
79
+ }
80
+ if (getenv("ORA_NLS10") == NULL) {
81
+ ruby_setenv("ORA_NLS10", "");
82
+ }
83
+ if (getenv("ORACLE_HOME") == NULL) {
84
+ ruby_setenv("ORACLE_HOME", ".");
85
+ }
86
+ }
87
+ #endif /* WIN32 */
88
+ rv = OCIInitialize(mode, NULL, NULL, NULL, NULL);
89
+ if (rv != OCI_SUCCESS) {
90
+ oci8_raise_init_error();
91
+ }
92
+ rv = OCIEnvInit(&oci8_envhp, OCI_DEFAULT, 0, NULL);
93
+ if (rv != OCI_SUCCESS) {
94
+ oci8_raise_init_error();
95
+ }
96
+ #ifdef RUBY_VM
97
+ id_thread_key = rb_intern("__oci8_errhp__");
98
+ error = oci8_tls_key_init(&oci8_tls_key);
99
+ if (error != 0) {
100
+ rb_raise(rb_eRuntimeError, "Cannot create thread local key (errno = %d)", error);
101
+ }
102
+ #else /* RUBY_VM */
103
+ rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_errhp, OCI_HTYPE_ERROR, 0, NULL);
104
+ if (rv != OCI_SUCCESS)
105
+ oci8_env_raise(oci8_envhp, rv);
273
106
  #endif
274
- rb_define_method(cOCIEnv, "alloc", oci8_handle_alloc, 1);
275
- rb_define_method(cOCIEnv, "logon", oci8_logon, 3);
276
107
  }