ruby-oci8 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/ChangeLog +366 -19
  2. data/Makefile +2 -8
  3. data/NEWS +111 -0
  4. data/README +4 -85
  5. data/VERSION +1 -1
  6. data/dist-files +9 -2
  7. data/ext/oci8/.document +1 -0
  8. data/ext/oci8/apiwrap.c.tmpl +12 -2
  9. data/ext/oci8/apiwrap.yml +37 -21
  10. data/ext/oci8/attr.c +23 -74
  11. data/ext/oci8/bind.c +93 -225
  12. data/ext/oci8/connection_pool.c +201 -0
  13. data/ext/oci8/encoding.c +117 -24
  14. data/ext/oci8/env.c +5 -10
  15. data/ext/oci8/error.c +171 -189
  16. data/ext/oci8/extconf.rb +6 -2
  17. data/ext/oci8/lob.c +81 -79
  18. data/ext/oci8/metadata.c +42 -177
  19. data/ext/oci8/object.c +55 -28
  20. data/ext/oci8/oci8.c +426 -294
  21. data/ext/oci8/oci8.h +84 -51
  22. data/ext/oci8/oci8lib.c +75 -53
  23. data/ext/oci8/ocidatetime.c +67 -88
  24. data/ext/oci8/ocihandle.c +78 -37
  25. data/ext/oci8/ocinumber.c +166 -109
  26. data/ext/oci8/oraconf.rb +68 -157
  27. data/ext/oci8/oradate.c +2 -7
  28. data/ext/oci8/stmt.c +40 -183
  29. data/ext/oci8/thread_util.c +85 -0
  30. data/ext/oci8/thread_util.h +30 -0
  31. data/lib/oci8.rb.in +19 -13
  32. data/lib/oci8/.document +2 -0
  33. data/lib/oci8/bindtype.rb +62 -45
  34. data/lib/oci8/connection_pool.rb +118 -0
  35. data/lib/oci8/datetime.rb +304 -320
  36. data/lib/oci8/encoding-init.rb +62 -30
  37. data/lib/oci8/encoding.yml +3 -3
  38. data/lib/oci8/metadata.rb +552 -497
  39. data/lib/oci8/object.rb +9 -9
  40. data/lib/oci8/oci8.rb +161 -2
  41. data/lib/oci8/ocihandle.rb +427 -0
  42. data/lib/oci8/properties.rb +31 -1
  43. data/ruby-oci8.gemspec +10 -3
  44. data/test/README +41 -3
  45. data/test/config.rb +16 -0
  46. data/test/test_all.rb +3 -0
  47. data/test/test_bind_string.rb +106 -0
  48. data/test/test_break.rb +33 -7
  49. data/test/test_clob.rb +13 -10
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +2 -2
  52. data/test/test_datetime.rb +26 -66
  53. data/test/test_encoding.rb +7 -3
  54. data/test/test_error.rb +88 -0
  55. data/test/test_metadata.rb +1356 -204
  56. data/test/test_oci8.rb +27 -8
  57. data/test/test_oranumber.rb +41 -0
  58. metadata +34 -9
  59. data/ext/oci8/xmldb.c +0 -383
@@ -2,11 +2,8 @@
2
2
  /*
3
3
  error.c - part of ruby-oci8
4
4
 
5
- Copyright (C) 2002-2010 KUBO Takehiro <kubo@jiubao.org>
5
+ Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
6
6
 
7
- =begin
8
- == OCIError
9
- =end
10
7
  */
11
8
  #include "oci8.h"
12
9
 
@@ -25,10 +22,9 @@ static VALUE eOCIStillExecuting;
25
22
  static VALUE eOCIContinue;
26
23
  static VALUE eOCISuccessWithInfo;
27
24
 
28
- static ID oci8_id_code;
29
- static ID oci8_id_message;
30
- static ID oci8_id_parse_error_offset;
31
- static ID oci8_id_sql;
25
+ static ID oci8_id_at_code;
26
+ static ID oci8_id_at_sql;
27
+ static ID oci8_id_at_parse_error_offset;
32
28
  static ID oci8_id_caller;
33
29
  static ID oci8_id_set_backtrace;
34
30
 
@@ -38,12 +34,7 @@ static ub4 errbufsiz;
38
34
 
39
35
  static OCIMsg *msghp;
40
36
 
41
- #ifndef OCI_DURATION_PROCESS
42
- #define OCI_DURATION_PROCESS ((OCIDuration)5)
43
- #endif
44
-
45
- NORETURN(static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line));
46
- NORETURN(static void set_backtrace_and_raise(VALUE exc, const char *file, int line));
37
+ static VALUE set_backtrace(VALUE exc, const char *file, int line);
47
38
 
48
39
  static VALUE get_error_msg(dvoid *errhp, ub4 type, const char *default_msg, sb4 *errcode_p)
49
40
  {
@@ -84,79 +75,32 @@ retry:
84
75
  return rb_external_str_new_with_enc(errbuf, len, oci8_encoding);
85
76
  }
86
77
 
87
- static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
78
+ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
88
79
  {
89
- VALUE vcodes = Qnil;
90
- VALUE vmessages = Qnil;
91
80
  VALUE exc;
92
- char errmsg[1024];
93
- sb4 errcode;
94
- ub4 recodeno;
81
+ char errmsg[128];
82
+ sb4 errcode = -1;
95
83
  VALUE msg;
96
- #ifdef OCI_ATTR_PARSE_ERROR_OFFSET
97
- VALUE vparse_error_offset = Qnil;
98
- #endif
99
- #ifdef OCI_ATTR_STATEMENT
100
- VALUE vsql = Qnil;
101
- #endif
102
- int i;
84
+ VALUE parse_error_offset = Qnil;
85
+ VALUE sql = Qnil;
103
86
  int rv;
87
+ int numarg = 1;
104
88
 
105
89
  switch (status) {
106
90
  case OCI_ERROR:
91
+ exc = eOCIError;
92
+ msg = get_error_msg(errhp, type, "Error", &errcode);
93
+ numarg = 4;
94
+ break;
107
95
  case OCI_SUCCESS_WITH_INFO:
108
- vcodes = rb_ary_new();
109
- vmessages = rb_ary_new();
110
- for (recodeno = 1;;recodeno++) {
111
- /* get error string */
112
- rv = OCIErrorGet(errhp, recodeno, NULL, &errcode, TO_ORATEXT(errmsg), sizeof(errmsg), type);
113
- if (rv != OCI_SUCCESS) {
114
- break;
115
- }
116
- /* chop error string */
117
- for (i = strlen(errmsg) - 1;i >= 0;i--) {
118
- if (errmsg[i] == '\n' || errmsg[i] == '\r') {
119
- errmsg[i] = '\0';
120
- } else {
121
- break;
122
- }
123
- }
124
- rb_ary_push(vcodes, INT2FIX(errcode));
125
- rb_ary_push(vmessages, rb_external_str_new_with_enc(errmsg, strlen(errmsg), oci8_encoding));
126
- }
127
- if (RARRAY_LEN(vmessages) > 0) {
128
- msg = RARRAY_PTR(vmessages)[0];
129
- } else {
130
- msg = rb_usascii_str_new_cstr("ERROR");
131
- }
132
- if (status == OCI_ERROR) {
133
- exc = eOCIError;
134
- } else {
135
- exc = eOCISuccessWithInfo;
136
- }
137
- #ifdef OCI_ATTR_PARSE_ERROR_OFFSET
138
- if (stmthp != NULL) {
139
- ub2 offset;
140
- rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &offset, 0, OCI_ATTR_PARSE_ERROR_OFFSET, errhp);
141
- if (rv == OCI_SUCCESS) {
142
- vparse_error_offset = INT2FIX(offset);
143
- }
144
- }
145
- #endif
146
- #ifdef OCI_ATTR_STATEMENT
147
- if (stmthp != NULL) {
148
- text *sql;
149
- ub4 size;
150
- rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &sql, &size, OCI_ATTR_STATEMENT, errhp);
151
- if (rv == OCI_SUCCESS) {
152
- vsql = rb_external_str_new_with_enc(TO_CHARPTR(sql), size, oci8_encoding);
153
- }
154
- }
155
- #endif
96
+ exc = eOCISuccessWithInfo;
97
+ msg = get_error_msg(errhp, type, "Error", &errcode);
98
+ numarg = 4;
156
99
  break;
157
100
  case OCI_NO_DATA:
158
101
  exc = eOCINoData;
159
102
  msg = get_error_msg(errhp, type, "No Data", &errcode);
103
+ numarg = 4;
160
104
  break;
161
105
  case OCI_INVALID_HANDLE:
162
106
  exc = eOCIInvalidHandle;
@@ -176,30 +120,28 @@ static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, c
176
120
  break;
177
121
  default:
178
122
  sprintf(errmsg, "Unknown error (%d)", status);
179
- exc = rb_eStandardError;
123
+ exc = eOCIException;
180
124
  msg = rb_usascii_str_new_cstr(errmsg);
181
125
  }
182
- exc = rb_funcall(exc, oci8_id_new, 1, msg);
183
- if (!NIL_P(vcodes)) {
184
- rb_ivar_set(exc, oci8_id_code, vcodes);
185
- }
186
- if (!NIL_P(vmessages)) {
187
- rb_ivar_set(exc, oci8_id_message, vmessages);
188
- }
189
- #ifdef OCI_ATTR_PARSE_ERROR_OFFSET
190
- if (!NIL_P(vparse_error_offset)) {
191
- rb_ivar_set(exc, oci8_id_parse_error_offset, vparse_error_offset);
192
- }
193
- #endif
194
- #ifdef OCI_ATTR_STATEMENT
195
- if (!NIL_P(vsql)) {
196
- rb_ivar_set(exc, oci8_id_sql, vsql);
126
+ if (stmthp != NULL) {
127
+ ub2 offset;
128
+ text *text;
129
+ ub4 size;
130
+
131
+ rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &offset, 0, OCI_ATTR_PARSE_ERROR_OFFSET, errhp);
132
+ if (rv == OCI_SUCCESS) {
133
+ parse_error_offset = INT2FIX(offset);
134
+ }
135
+ rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &text, &size, OCI_ATTR_STATEMENT, errhp);
136
+ if (rv == OCI_SUCCESS) {
137
+ sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
138
+ }
197
139
  }
198
- #endif
199
- set_backtrace_and_raise(exc, file, line);
140
+ exc = rb_funcall(exc, oci8_id_new, numarg, msg, INT2FIX(errcode), sql, parse_error_offset);
141
+ return set_backtrace(exc, file, line);
200
142
  }
201
143
 
202
- static void set_backtrace_and_raise(VALUE exc, const char *file, int line)
144
+ static VALUE set_backtrace(VALUE exc, const char *file, int line)
203
145
  {
204
146
  char errmsg[64];
205
147
  VALUE backtrace;
@@ -215,87 +157,30 @@ static void set_backtrace_and_raise(VALUE exc, const char *file, int line)
215
157
  rb_ary_unshift(backtrace, rb_usascii_str_new_cstr(errmsg));
216
158
  rb_funcall(exc, oci8_id_set_backtrace, 1, backtrace);
217
159
  }
218
- rb_exc_raise(exc);
160
+ return exc;
219
161
  }
220
162
 
163
+ /*
164
+ * call-seq:
165
+ * OCI8.new(message, code = nil, sql = nil, parse_error_offset = nil)
166
+ *
167
+ * Creates a new OCIError object.
168
+ */
221
169
  static VALUE oci8_error_initialize(int argc, VALUE *argv, VALUE self)
222
170
  {
223
171
  VALUE msg;
224
172
  VALUE code;
173
+ VALUE sql;
174
+ VALUE parse_error_offset;
225
175
 
226
- rb_scan_args(argc, argv, "02", &msg, &code);
176
+ rb_scan_args(argc, argv, "04", &msg, &code, &sql, &parse_error_offset);
227
177
  rb_call_super(argc > 1 ? 1 : argc, argv);
228
- if (!NIL_P(code)) {
229
- rb_ivar_set(self, oci8_id_code, rb_ary_new3(1, code));
230
- }
178
+ rb_ivar_set(self, oci8_id_at_code, code);
179
+ rb_ivar_set(self, oci8_id_at_sql, sql);
180
+ rb_ivar_set(self, oci8_id_at_parse_error_offset, parse_error_offset);
231
181
  return Qnil;
232
182
  }
233
183
 
234
- /*
235
- =begin
236
- --- OCIError#code()
237
- =end
238
- */
239
- static VALUE oci8_error_code(VALUE self)
240
- {
241
- VALUE ary = rb_ivar_get(self, oci8_id_code);
242
- if (RARRAY_LEN(ary) == 0) {
243
- return Qnil;
244
- }
245
- return RARRAY_PTR(ary)[0];
246
- }
247
-
248
- /*
249
- =begin
250
- --- OCIError#codes()
251
- =end
252
- */
253
- static VALUE oci8_error_code_array(VALUE self)
254
- {
255
- return rb_ivar_get(self, oci8_id_code);
256
- }
257
-
258
- /*
259
- =begin
260
- --- OCIError#message()
261
- =end
262
- */
263
-
264
- /*
265
- =begin
266
- --- OCIError#messages()
267
- =end
268
- */
269
- static VALUE oci8_error_message_array(VALUE self)
270
- {
271
- return rb_ivar_get(self, oci8_id_message);
272
- }
273
-
274
- #ifdef OCI_ATTR_PARSE_ERROR_OFFSET
275
- /*
276
- =begin
277
- --- OCIError#parseErrorOffset()
278
- =end
279
- */
280
- static VALUE oci8_error_parse_error_offset(VALUE self)
281
- {
282
- return rb_ivar_get(self, oci8_id_parse_error_offset);
283
- }
284
- #endif
285
-
286
- #ifdef OCI_ATTR_STATEMENT
287
- /*
288
- =begin
289
- --- OCIError#sql()
290
- (Oracle 8.1.6 or later)
291
- =end
292
- */
293
- static VALUE oci8_error_sql(VALUE self)
294
- {
295
- return rb_ivar_get(self, oci8_id_sql);
296
- }
297
- #endif
298
-
299
184
  sb4 oci8_get_error_code(OCIError *errhp)
300
185
  {
301
186
  sb4 errcode = -1;
@@ -308,18 +193,17 @@ void Init_oci8_error(void)
308
193
  errbufsiz = ERRBUF_EXPAND_LEN;
309
194
  errbuf = xmalloc(errbufsiz);
310
195
 
311
- oci8_id_code = rb_intern("code");
312
- oci8_id_message = rb_intern("message");
313
- oci8_id_parse_error_offset = rb_intern("parse_error_offset");
314
- oci8_id_sql = rb_intern("sql");
196
+ oci8_id_at_code = rb_intern("@code");
197
+ oci8_id_at_sql = rb_intern("@sql");
198
+ oci8_id_at_parse_error_offset = rb_intern("@parse_error_offset");
315
199
  oci8_id_caller = rb_intern("caller");
316
200
  oci8_id_set_backtrace = rb_intern("set_backtrace");
317
201
 
318
202
  eOCIException = rb_define_class("OCIException", rb_eStandardError);
319
203
  eOCIBreak = rb_define_class("OCIBreak", eOCIException);
320
204
 
321
- eOCINoData = rb_define_class("OCINoData", eOCIException);
322
205
  eOCIError = rb_define_class("OCIError", eOCIException);
206
+ eOCINoData = rb_define_class("OCINoData", eOCIError);
323
207
  eOCIInvalidHandle = rb_define_class("OCIInvalidHandle", eOCIException);
324
208
  eOCINeedData = rb_define_class("OCINeedData", eOCIException);
325
209
  eOCIStillExecuting = rb_define_class("OCIStillExecuting", eOCIException);
@@ -327,35 +211,28 @@ void Init_oci8_error(void)
327
211
  eOCISuccessWithInfo = rb_define_class("OCISuccessWithInfo", eOCIError);
328
212
 
329
213
  rb_define_method(eOCIError, "initialize", oci8_error_initialize, -1);
330
- rb_define_method(eOCIError, "code", oci8_error_code, 0);
331
- rb_define_method(eOCIError, "codes", oci8_error_code_array, 0);
332
- rb_define_method(eOCIError, "messages", oci8_error_message_array, 0);
333
- #ifdef OCI_ATTR_PARSE_ERROR_OFFSET
334
- rb_define_method(eOCIError, "parseErrorOffset", oci8_error_parse_error_offset, 0);
335
- #endif
336
- #ifdef OCI_ATTR_STATEMENT
337
- rb_define_method(eOCIError, "sql", oci8_error_sql, 0);
338
- #endif
214
+ rb_define_attr(eOCIError, "code", 1, 0);
215
+ rb_define_attr(eOCIError, "sql", 1, 0);
216
+ rb_define_attr(eOCIError, "parse_error_offset", 1, 0);
217
+ rb_define_alias(eOCIError, "parseErrorOffset", "parse_error_offset");
339
218
  }
340
219
 
341
220
  void oci8_do_raise(OCIError *errhp, sword status, OCIStmt *stmthp, const char *file, int line)
342
221
  {
343
- oci8_raise2(errhp, status, OCI_HTYPE_ERROR, stmthp, file, line);
222
+ rb_exc_raise(oci8_make_exc(errhp, status, OCI_HTYPE_ERROR, stmthp, file, line));
344
223
  }
345
224
 
346
225
  void oci8_do_env_raise(OCIEnv *envhp, sword status, const char *file, int line)
347
226
  {
348
- oci8_raise2(envhp, status, OCI_HTYPE_ENV, NULL, file, line);
227
+ rb_exc_raise(oci8_make_exc(envhp, status, OCI_HTYPE_ENV, NULL, file, line));
349
228
  }
350
229
 
351
230
  void oci8_do_raise_init_error(const char *file, int line)
352
231
  {
353
232
  VALUE msg = rb_usascii_str_new_cstr("OCI Library Initialization Error");
354
- VALUE exc = rb_funcall(eOCIError, oci8_id_new, 1, msg);
233
+ VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
355
234
 
356
- rb_ivar_set(exc, oci8_id_code, rb_ary_new3(1, INT2FIX(-1)));
357
- rb_ivar_set(exc, oci8_id_message, rb_ary_new3(1, msg));
358
- set_backtrace_and_raise(exc, file, line);
235
+ rb_exc_raise(set_backtrace(exc, file, line));
359
236
  }
360
237
 
361
238
  VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
@@ -367,7 +244,7 @@ VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
367
244
 
368
245
  if (have_OCIMessageGet) {
369
246
  if (msghp == NULL) {
370
- oci_lc(OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_ORATEXT("rdbms"), TO_ORATEXT("ora"), OCI_DURATION_PROCESS));
247
+ chkerr(OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_CONST_ORATEXT("rdbms"), TO_CONST_ORATEXT("ora"), OCI_DURATION_PROCESS));
371
248
  }
372
249
  errmsg = TO_CHARPTR(OCIMessageGet(msghp, msgno, NULL, 0));
373
250
  }
@@ -388,9 +265,114 @@ VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
388
265
  void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
389
266
  {
390
267
  VALUE msg = oci8_get_error_message(msgno, default_msg);
391
- VALUE exc = rb_funcall(eOCIError, oci8_id_new, 1, msg);
268
+ VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
269
+
270
+ rb_exc_raise(set_backtrace(exc, file, line));
271
+ }
392
272
 
393
- rb_ivar_set(exc, oci8_id_code, rb_ary_new3(1, INT2FIX(-1)));
394
- rb_ivar_set(exc, oci8_id_message, rb_ary_new3(1, msg));
395
- set_backtrace_and_raise(exc, file, line);
273
+ void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line)
274
+ {
275
+ if (status != OCI_SUCCESS) {
276
+ VALUE exc = oci8_make_exc(oci8_errhp, status, OCI_HTYPE_ERROR, stmthp, file, line);
277
+ while (base != NULL) {
278
+ if (base->type == OCI_HTYPE_SVCCTX) {
279
+ rb_ivar_set(base->self, oci8_id_at_last_error, exc);
280
+ break;
281
+ }
282
+ base = base->parent;
283
+ }
284
+ if (status != OCI_SUCCESS_WITH_INFO) {
285
+ rb_exc_raise(exc);
286
+ }
287
+ }
396
288
  }
289
+
290
+ /*
291
+ * Document-class: OCIException
292
+ *
293
+ * The superclass for all exceptions raised by ruby-oci8.
294
+ *
295
+ * The following exceptions are defined as subclasses of OCIException
296
+ * These exceptions are raised when Oracle Call Interface functions
297
+ * return with an error status.
298
+ *
299
+ * - OCIBreak
300
+ * - OCIContinue
301
+ * - OCIError
302
+ * - OCISuccessWithInfo
303
+ * - OCINoData (It had been a subclass of OCIException, not OCIError, until ruby-oci8 2.0)
304
+ * - OCIInvalidHandle
305
+ * - OCINeedData
306
+ * - OCIStillExecuting
307
+ */
308
+
309
+ /*
310
+ * Document-class: OCIBreak
311
+ *
312
+ * Subclass of OCIException
313
+ *
314
+ * Raised when a SQL execution is cancelled by OCI8#break.
315
+ */
316
+
317
+ /*
318
+ * Document-class: OCINoData
319
+ *
320
+ * Subclass of OCIError from ruby-oci8 2.1.
321
+ * It had been a subclass of OCIException until ruby-oci8 2.0.
322
+ *
323
+ * Raised when PL/SQL NO_DATA_FOUND exception is got.
324
+ */
325
+
326
+ /*
327
+ * Document-class: OCIError
328
+ *
329
+ * Subclass of OCIException
330
+ *
331
+ * The following exceptions are defined as subclasses of OCIError.
332
+ *
333
+ * - OCISuccessWithInfo
334
+ * - OCINoData (It had been a subclass of OCIException, not OCIError, until ruby-oci8 2.0)
335
+ *
336
+ * Raised when underlying Oracle Call Interface failed with an Oracle error code
337
+ * such as ORA-00001.
338
+ */
339
+
340
+ /*
341
+ * Document-class: OCIInvalidHandle
342
+ *
343
+ * Subclass of OCIException
344
+ *
345
+ * Raised when an invalid handle is passed to underlying Oracle Call Interface.
346
+ * Report to the ruby-oci8 author if it is raised.
347
+ */
348
+
349
+ /*
350
+ * Document-class: OCINeedData
351
+ *
352
+ * Subclass of OCIException
353
+ *
354
+ * Report to the ruby-oci8 author if it is raised.
355
+ */
356
+
357
+ /*
358
+ * Document-class: OCIStillExecuting
359
+ *
360
+ * Subclass of OCIError
361
+ *
362
+ * Report to the ruby-oci8 author if it is raised.
363
+ */
364
+
365
+ /*
366
+ * Document-class: OCIContinue
367
+ *
368
+ * Subclass of OCIException
369
+ *
370
+ * Report to the ruby-oci8 author if it is raised.
371
+ */
372
+
373
+ /*
374
+ * Document-class: OCISuccessWithInfo
375
+ *
376
+ * Subclass of OCIError
377
+ *
378
+ */