ruby-oci8 2.1.8 → 2.2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -82,8 +82,24 @@ Init_oci8lib()
82
82
 
83
83
  #ifdef RUNTIME_API_CHECK
84
84
  Init_oci8_apiwrap();
85
- if (oracle_client_version < ORAVER_9_0) {
86
- rb_raise(rb_eLoadError, "Oracle 8 (8.0) and Oracle 8i (8.1) is not supported anymore!");
85
+ if (oracle_client_version < ORAVER_10_1) {
86
+ const char *oraver;
87
+ const char *ruby_oci8_ver;
88
+ if (oracle_client_version >= ORAVER_9_2) {
89
+ oraver = "9iR2";
90
+ ruby_oci8_ver = "2.1.x";
91
+ } else if (oracle_client_version >= ORAVER_9_0) {
92
+ oraver = "9iR1";
93
+ ruby_oci8_ver = "2.1.x";
94
+ } else if (oracle_client_version >= ORAVER_8_1) {
95
+ oraver = "8i";
96
+ ruby_oci8_ver = "2.0.x";
97
+ } else {
98
+ oraver = "8";
99
+ ruby_oci8_ver = "2.0.x";
100
+ }
101
+ rb_raise(rb_eLoadError, "Ruby-oci8 %s doesn't support Oracle %s. Use ruby-oci8 %s instead.",
102
+ OCI8LIB_VERSION, oraver, ruby_oci8_ver);
87
103
  }
88
104
 
89
105
  if (have_OCIClientVersion) {
@@ -135,6 +151,9 @@ Init_oci8lib()
135
151
  Init_oci8_metadata(cOCI8);
136
152
  Init_oci8_lob(cOCI8);
137
153
 
154
+ /* OCI8::Util */
155
+ Init_oci8_util(cOCI8);
156
+
138
157
  /* allocate a temporary errhp to pass Init_oci_number() */
139
158
  rv = OCIEnvCreate(&envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
140
159
  if (rv != OCI_SUCCESS) {
@@ -223,8 +242,6 @@ void oci8_unlink_from_parent(oci8_base_t *base)
223
242
  base->parent = NULL;
224
243
  }
225
244
 
226
- #ifdef NATIVE_THREAD_WITH_GVL
227
-
228
245
  static void oci8_unblock_func(void *user_data)
229
246
  {
230
247
  oci8_svcctx_t *svcctx = (oci8_svcctx_t *)user_data;
@@ -275,7 +292,6 @@ static VALUE protected_call(VALUE data)
275
292
  return rv;
276
293
  }
277
294
 
278
- /* ruby 1.9 */
279
295
  sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data)
280
296
  {
281
297
  OCIError *errhp = oci8_errhp;
@@ -330,66 +346,6 @@ sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *
330
346
  return (sword)(VALUE)func(data);
331
347
  }
332
348
  }
333
- #else /* NATIVE_THREAD_WITH_GVL */
334
-
335
- /* ruby 1.8 */
336
- typedef struct {
337
- oci8_svcctx_t *svcctx;
338
- void *(*func)(void *);
339
- void *data;
340
- } blocking_region_arg_t;
341
-
342
- static VALUE blocking_function_execute(blocking_region_arg_t *arg)
343
- {
344
- oci8_svcctx_t *svcctx = arg->svcctx;
345
- void *(*func)(void *) = arg->func;
346
- void *data = arg->data;
347
- struct timeval tv;
348
- sword rv;
349
-
350
- tv.tv_sec = 0;
351
- tv.tv_usec = 10000;
352
- svcctx->executing_thread = rb_thread_current();
353
- while ((rv = (sword)(VALUE)func(data)) == OCI_STILL_EXECUTING) {
354
- rb_thread_wait_for(tv);
355
- if (tv.tv_usec < 500000)
356
- tv.tv_usec <<= 1;
357
- }
358
- if (rv == OCI_ERROR) {
359
- if (oci8_get_error_code(oci8_errhp) == 1013) {
360
- OCIReset(svcctx->base.hp.ptr, oci8_errhp);
361
- svcctx->executing_thread = Qnil;
362
- rb_raise(eOCIBreak, "Canceled by user request.");
363
- }
364
- }
365
- svcctx->executing_thread = Qnil;
366
- return rv;
367
- }
368
-
369
- static VALUE blocking_function_ensure(oci8_svcctx_t *svcctx)
370
- {
371
- if (!NIL_P(svcctx->executing_thread)) {
372
- /* The thread is killed. */
373
- OCIBreak(svcctx->base.hp.ptr, oci8_errhp);
374
- OCIReset(svcctx->base.hp.ptr, oci8_errhp);
375
- svcctx->executing_thread = Qnil;
376
- }
377
- return Qnil;
378
- }
379
-
380
- sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data)
381
- {
382
- blocking_region_arg_t arg;
383
-
384
- arg.svcctx = svcctx;
385
- arg.func = func;
386
- arg.data = data;
387
- if (!NIL_P(svcctx->executing_thread)) {
388
- rb_raise(rb_eRuntimeError, "executing in another thread");
389
- }
390
- return (sword)rb_ensure(blocking_function_execute, (VALUE)&arg, blocking_function_ensure, (VALUE)svcctx);
391
- }
392
- #endif /* NATIVE_THREAD_WITH_GVL */
393
349
 
394
350
  typedef struct {
395
351
  oci8_svcctx_t *svcctx;
@@ -433,8 +389,9 @@ static VALUE exec_sql(cb_arg_t *arg)
433
389
  if (rv != OCI_SUCCESS) {
434
390
  oci8_env_raise(oci8_envhp, rv);
435
391
  }
436
- chker2(OCIStmtPrepare(arg->stmtp, oci8_errhp, (text*)arg->sql_text,
437
- strlen(arg->sql_text), OCI_NTV_SYNTAX, OCI_DEFAULT),
392
+ chker2(OCIStmtPrepare2(arg->svcctx->base.hp.svc, &arg->stmtp, oci8_errhp,
393
+ (text*)arg->sql_text, strlen(arg->sql_text), NULL, 0,
394
+ OCI_NTV_SYNTAX, OCI_DEFAULT),
438
395
  &arg->svcctx->base);
439
396
  for (pos = 0; pos < arg->num_define_vars; pos++) {
440
397
  arg->define_vars[pos].hp = NULL;
@@ -473,7 +430,7 @@ static VALUE exec_sql(cb_arg_t *arg)
473
430
  static VALUE ensure_func(cb_arg_t *arg)
474
431
  {
475
432
  if (arg->stmtp != NULL) {
476
- OCIHandleFree(arg->stmtp, OCI_HTYPE_STMT);
433
+ OCIStmtRelease(arg->stmtp, oci8_errhp, NULL, 0, OCI_DEFAULT);
477
434
  }
478
435
  return Qnil;
479
436
  }
@@ -558,7 +515,7 @@ void *oci8_find_symbol(const char *symbol_name)
558
515
  }
559
516
  if (handle == NULL) {
560
517
  VALUE msg;
561
- const char *ary = RARRAY_CONST_PTR(err);
518
+ const VALUE *arr = RARRAY_CONST_PTR(err);
562
519
 
563
520
  msg = rb_str_buf_new(NUM_SONAMES * 50);
564
521
  for (idx = 0; idx < NUM_SONAMES; idx++) {
@@ -354,26 +354,8 @@ OCIInterval *oci8_set_ociinterval_ym(OCIInterval *intvl, VALUE val)
354
354
  }
355
355
  year = NUM2INT(RARRAY_AREF(val, 0));
356
356
  month = NUM2INT(RARRAY_AREF(val, 1));
357
- if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) {
358
- chkerr(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp,
359
- year, month, intvl));
360
- } else {
361
- /* Workaround for Bug 2227982 */
362
- char buf[64];
363
- const char *sign = "";
364
-
365
- if (year < 0 && month != 0) {
366
- year += 1;
367
- month -= 12;
368
- }
369
- if (year < 0 || month < 0) {
370
- sign = "-";
371
- year = -year;
372
- month = -month;
373
- }
374
- sprintf(buf, "%s%d-%d", sign, year, month);
375
- chkerr(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
376
- }
357
+ chkerr(OCIIntervalSetYearMonth(oci8_envhp, oci8_errhp,
358
+ year, month, intvl));
377
359
  return intvl;
378
360
  }
379
361
 
@@ -409,32 +391,8 @@ OCIInterval *oci8_set_ociinterval_ds(OCIInterval *intvl, VALUE val)
409
391
  minute = NUM2INT(RARRAY_AREF(val, 2));
410
392
  sec = NUM2INT(RARRAY_AREF(val, 3));
411
393
  fsec = NUM2INT(RARRAY_AREF(val, 4));
412
- if (oracle_client_version >= ORAVERNUM(9, 2, 0, 3, 0)) {
413
- chkerr(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp,
414
- day, hour, minute, sec, fsec, intvl));
415
- } else {
416
- /* Workaround for Bug 2227982 */
417
- char buf[64];
418
- const char *sign = "";
419
-
420
- if (day == 0) {
421
- if (hour < 0) {
422
- sign = "-";
423
- hour = -hour;
424
- } else if (minute < 0) {
425
- sign = "-";
426
- minute = -minute;
427
- } else if (sec < 0) {
428
- sign = "-";
429
- sec = -sec;
430
- } else if (fsec < 0) {
431
- sign = "-";
432
- fsec = -fsec;
433
- }
434
- }
435
- sprintf(buf, "%s%d %02d:%02d:%02d.%09d", sign, day, hour, minute, sec, fsec);
436
- chkerr(OCIIntervalFromText(oci8_envhp, oci8_errhp, (text*)buf, strlen(buf), intvl));
437
- }
394
+ chkerr(OCIIntervalSetDaySecond(oci8_envhp, oci8_errhp,
395
+ day, hour, minute, sec, fsec, intvl));
438
396
  return intvl;
439
397
  }
440
398
 
@@ -11,12 +11,6 @@
11
11
  #include <math.h>
12
12
  #include "oranumber_util.h"
13
13
 
14
- #ifndef RB_NUM_COERCE_FUNCS_NEED_OPID
15
- /* ruby 1.8 */
16
- #define rb_num_coerce_cmp(x, y, id) rb_num_coerce_cmp((x), (y))
17
- #define rb_num_coerce_bin(x, y, id) rb_num_coerce_bin((x), (y))
18
- #endif
19
-
20
14
  int oci8_float_conversion_type_is_ruby = 1;
21
15
 
22
16
  #ifndef INFINITY
@@ -32,9 +26,7 @@ static ID id_denominator;
32
26
  static ID id_Rational;
33
27
  static ID id_BigDecimal;
34
28
 
35
- #ifndef rb_Rational2
36
29
  static VALUE cRational;
37
- #endif
38
30
  static VALUE cBigDecimal;
39
31
 
40
32
  static VALUE cOCINumber;
@@ -52,11 +44,6 @@ static OCINumber const_mPI2; /* -PI/2 */
52
44
  #endif
53
45
  #define RBOCI8_T_ORANUMBER (T_MASK + 1)
54
46
  #define RBOCI8_T_BIGDECIMAL (T_MASK + 2)
55
- #ifdef rb_Rational2
56
- #define RBOCI8_T_RATIONAL T_RATIONAL
57
- #else
58
- #define RBOCI8_T_RATIONAL (T_MASK + 3)
59
- #endif
60
47
 
61
48
  static int rboci8_type(VALUE obj)
62
49
  {
@@ -64,21 +51,19 @@ static int rboci8_type(VALUE obj)
64
51
  VALUE klass;
65
52
 
66
53
  switch (type) {
67
- #ifndef rb_Rational2
68
54
  case T_OBJECT:
69
55
  klass = CLASS_OF(obj);
70
56
  if (cRational != 0) {
71
57
  if (klass == cRational) {
72
- return RBOCI8_T_RATIONAL;
58
+ return T_RATIONAL;
73
59
  }
74
60
  } else {
75
61
  if (strcmp(rb_class2name(klass), "Rational") == 0) {
76
62
  cRational = rb_const_get(rb_cObject, id_Rational);
77
- return RBOCI8_T_RATIONAL;
63
+ return T_RATIONAL;
78
64
  }
79
65
  }
80
66
  break;
81
- #endif
82
67
  case T_DATA:
83
68
  klass = CLASS_OF(obj);
84
69
  if (klass == cOCINumber) {
@@ -866,7 +851,7 @@ static VALUE onum_coerce(VALUE self, VALUE other)
866
851
  return rb_assoc_new(oci8_make_ocinumber(&n, oci8_errhp), self);
867
852
  case T_FLOAT:
868
853
  return rb_assoc_new(other, onum_to_f(self));
869
- case RBOCI8_T_RATIONAL:
854
+ case T_RATIONAL:
870
855
  return rb_assoc_new(other, onum_to_r(self));
871
856
  case RBOCI8_T_BIGDECIMAL:
872
857
  return rb_assoc_new(other, onum_to_d(self));
@@ -925,7 +910,7 @@ static VALUE onum_add(VALUE lhs, VALUE rhs)
925
910
  return oci8_make_ocinumber(&r, errhp);
926
911
  case T_FLOAT:
927
912
  return rb_funcall(onum_to_f(lhs), oci8_id_add_op, 1, rhs);
928
- case RBOCI8_T_RATIONAL:
913
+ case T_RATIONAL:
929
914
  return rb_funcall(onum_to_r(lhs), oci8_id_add_op, 1, rhs);
930
915
  case RBOCI8_T_BIGDECIMAL:
931
916
  return rb_funcall(onum_to_d(lhs), oci8_id_add_op, 1, rhs);
@@ -966,7 +951,7 @@ static VALUE onum_sub(VALUE lhs, VALUE rhs)
966
951
  return oci8_make_ocinumber(&r, errhp);
967
952
  case T_FLOAT:
968
953
  return rb_funcall(onum_to_f(lhs), oci8_id_sub_op, 1, rhs);
969
- case RBOCI8_T_RATIONAL:
954
+ case T_RATIONAL:
970
955
  return rb_funcall(onum_to_r(lhs), oci8_id_sub_op, 1, rhs);
971
956
  case RBOCI8_T_BIGDECIMAL:
972
957
  return rb_funcall(onum_to_d(lhs), oci8_id_sub_op, 1, rhs);
@@ -1007,7 +992,7 @@ static VALUE onum_mul(VALUE lhs, VALUE rhs)
1007
992
  return oci8_make_ocinumber(&r, errhp);
1008
993
  case T_FLOAT:
1009
994
  return rb_funcall(onum_to_f(lhs), oci8_id_mul_op, 1, rhs);
1010
- case RBOCI8_T_RATIONAL:
995
+ case T_RATIONAL:
1011
996
  return rb_funcall(onum_to_r(lhs), oci8_id_mul_op, 1, rhs);
1012
997
  case RBOCI8_T_BIGDECIMAL:
1013
998
  return rb_funcall(onum_to_d(lhs), oci8_id_mul_op, 1, rhs);
@@ -1056,7 +1041,7 @@ static VALUE onum_div(VALUE lhs, VALUE rhs)
1056
1041
  return oci8_make_ocinumber(&r, errhp);
1057
1042
  case T_FLOAT:
1058
1043
  return rb_funcall(onum_to_f(lhs), oci8_id_div_op, 1, rhs);
1059
- case RBOCI8_T_RATIONAL:
1044
+ case T_RATIONAL:
1060
1045
  return rb_funcall(onum_to_r(lhs), oci8_id_div_op, 1, rhs);
1061
1046
  case RBOCI8_T_BIGDECIMAL:
1062
1047
  return rb_funcall(onum_to_d(lhs), oci8_id_div_op, 1, rhs);
@@ -1439,15 +1424,7 @@ static VALUE onum_to_r(VALUE self)
1439
1424
  } else {
1440
1425
  y = rb_funcall(INT2FIX(10), rb_intern("**"), 1, INT2FIX(nshift));
1441
1426
  }
1442
- #ifdef rb_Rational2
1443
1427
  return rb_Rational(x, y);
1444
- #else
1445
- if (!cRational) {
1446
- rb_require("rational");
1447
- cRational = rb_const_get(rb_cObject, id_Rational);
1448
- }
1449
- return rb_funcall(rb_cObject, id_Rational, 2, x, y);
1450
- #endif
1451
1428
  }
1452
1429
 
1453
1430
  /*
@@ -334,9 +334,10 @@ Backtrace:
334
334
  #{$!.backtrace.join("\n ")}
335
335
  ---------------------------------------------------
336
336
  See:
337
- * http://rubydoc.info/gems/ruby-oci8/file/docs/install-full-client.md for Oracle full client
338
- * http://rubydoc.info/gems/ruby-oci8/file/docs/install-instant-client.md for Oracle instant client
339
- * http://ruby-oci8.rubyforge.org/en/file.report-installation-issue.html to report an issue.
337
+ * http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-full-client.md for Oracle full client
338
+ * http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-instant-client.md for Oracle instant client
339
+ * http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-on-osx.md for OS X
340
+ * http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/report-installation-issue.md to report an issue.
340
341
 
341
342
  EOS
342
343
  exc = RuntimeError.new
@@ -518,6 +519,64 @@ EOS
518
519
  end
519
520
  end
520
521
  end
522
+ when /darwin/
523
+ fallback_path = ENV['DYLD_FALLBACK_LIBRARY_PATH']
524
+ if fallback_path.nil?
525
+ fallback_path = "#{ENV['HOME']}/lib:/usr/local/lib:/lib:/usr/lib"
526
+ end
527
+ puts " checking DYLD_FALLBACK_LIBRARY_PATH..."
528
+ ld_path, file = check_lib_in_path(fallback_path, glob_name, check_proc)
529
+ if ld_path.nil?
530
+ puts " checking OCI_DIR..."
531
+ ld_path, file = check_lib_in_path(ENV['OCI_DIR'], glob_name, check_proc)
532
+ if ld_path
533
+ puts " checking dependent shared libraries in #{file}..."
534
+ open("|otool -L #{file}") do |f|
535
+ f.gets # discard the first line
536
+ while line = f.gets
537
+ line =~ /^\s+(\S+)/
538
+ libname = $1
539
+ case libname
540
+ when /^@rpath\/libclntsh\.dylib/, /^@rpath\/libnnz\d\d\.dylib/, /^@loader_path\/libnnz\d\d\.dylib/
541
+ # No need to check the real path.
542
+ # The current instant client doesn't use @rpath or @loader_path.
543
+ when /\/libclntsh\.dylib/, /\/libnnz\d\d.dylib/
544
+ raise <<EOS unless File.exists?(libname)
545
+ The output of "otool -L #{file}" is:
546
+ | #{IO.readlines("|otool -L #{file}").join(' | ')}
547
+ Ruby-oci8 doesn't work without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH
548
+ because the dependent file "#{libname}" doesn't exist.
549
+
550
+ If you need to use ruby-oci8 without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH,
551
+ download "fix_oralib.rb" in https://github.com/kubo/fix_oralib_osx
552
+ and execute it in the directory "#{File.dirname(file)}" as follows to fix the path.
553
+
554
+ cd #{File.dirname(file)}
555
+ curl -O https://raw.githubusercontent.com/kubo/fix_oralib_osx/master/fix_oralib.rb
556
+ ruby fix_oralib.rb
557
+
558
+ Note: DYLD_* environment variables are unavailable for security reasons on OS X 10.11 El Capitan.
559
+ EOS
560
+ end
561
+ end
562
+ end
563
+ end
564
+ end
565
+ if ld_path.nil?
566
+ raise <<EOS
567
+ Set the environment variable DYLD_LIBRARY_PATH, DYLD_FALLBACK_LIBRARY_PATH or
568
+ OCI_DIR to point to the Instant client directory.
569
+
570
+ If DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH is set, the environment
571
+ variable must be set at runtime also.
572
+
573
+ If OCI_DIR is set, dependent shared library paths are checked. If the checking
574
+ is passed, ruby-oci8 works without DYLD_LIBRARY_PATH or DYLD_FALLBACK_LIBRARY_PATH.
575
+
576
+ Note: OCI_DIR should be absolute path.
577
+ Note: DYLD_* environment variables are unavailable for security reasons on OS X 10.11 El Capitan.
578
+ EOS
579
+ end
521
580
  end
522
581
  end
523
582
 
@@ -535,6 +594,7 @@ EOS
535
594
  end
536
595
 
537
596
  def self.check_lib_in_path(paths, glob_name, check_proc)
597
+ return nil if paths.nil?
538
598
  paths.split(File::PATH_SEPARATOR).each do |path|
539
599
  next if path.nil? or path == ''
540
600
  print " checking #{path}... "
@@ -689,7 +749,7 @@ EOS
689
749
  case RUBY_PLATFORM
690
750
  when /solaris/
691
751
  " -L#{lib_dir} -R#{lib_dir} -lclntsh"
692
- when /linux/
752
+ when /linux/,/darwin/
693
753
  " -L#{lib_dir} -Wl,-rpath,#{lib_dir} -lclntsh"
694
754
  else
695
755
  " -L#{lib_dir} -lclntsh"
@@ -74,10 +74,10 @@ static VALUE oci8_stmt_initialize(VALUE self, VALUE svc, VALUE sql)
74
74
 
75
75
  svcctx = oci8_get_svcctx(svc);
76
76
  oci8_check_pid_consistency(svcctx);
77
- if (!NIL_P(sql) && oracle_client_version >= ORAVER_9_2) {
77
+ if (!NIL_P(sql)) {
78
78
  OCI8SafeStringValue(sql);
79
79
 
80
- rv = OCIStmtPrepare2_nb(svcctx, svcctx->base.hp.svc, &stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT);
80
+ rv = OCIStmtPrepare2(svcctx->base.hp.svc, &stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT);
81
81
  if (IS_OCI_ERROR(rv)) {
82
82
  chker2(rv, &svcctx->base);
83
83
  }
@@ -89,13 +89,6 @@ static VALUE oci8_stmt_initialize(VALUE self, VALUE svc, VALUE sql)
89
89
  oci8_env_raise(oci8_envhp, rv);
90
90
  }
91
91
  stmt->base.type = OCI_HTYPE_STMT;
92
- if (!NIL_P(sql)) {
93
- OCI8SafeStringValue(sql);
94
- rv = OCIStmtPrepare(stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
95
- if (IS_OCI_ERROR(rv)) {
96
- chker3(rv, &svcctx->base, stmt->base.hp.stmt);
97
- }
98
- }
99
92
  }
100
93
  RB_OBJ_WRITE(stmt->base.self, &stmt->svc, svc);
101
94
 
@@ -7,8 +7,6 @@
7
7
  #include "oci8.h"
8
8
  #include <errno.h>
9
9
 
10
- #ifdef USE_THREAD_LOCAL_ERRHP
11
-
12
10
  #ifndef WIN32
13
11
  #include <pthread.h>
14
12
  static pthread_attr_t detached_thread_attr;
@@ -81,5 +79,3 @@ int oci8_run_native_thread(void *(*func)(void *), void *arg)
81
79
  return rv;
82
80
  }
83
81
  #endif /* WIN32 */
84
-
85
- #endif /* USE_THREAD_LOCAL_ERRHP */