ruby-oci8 2.0.4 → 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -61,6 +61,14 @@ static void oci8_handle_mark(oci8_base_t *base)
61
61
 
62
62
  static void oci8_handle_cleanup(oci8_base_t *base)
63
63
  {
64
+ if (oci8_in_finalizer) {
65
+ /* Do nothing when the program exits.
66
+ * The first two words of memory addressed by VALUE datatype is
67
+ * changed in finalizer. If a ruby function which access it such
68
+ * as rb_obj_is_kind_of is called, it may cause SEGV.
69
+ */
70
+ return;
71
+ }
64
72
  oci8_base_free(base);
65
73
  xfree(base);
66
74
  }
@@ -74,7 +82,7 @@ static VALUE oci8_s_allocate(VALUE klass)
74
82
 
75
83
  superklass = klass;
76
84
  while (!RTEST(rb_ivar_defined(superklass, oci8_id_oci8_class))) {
77
- superklass = RCLASS_SUPER(superklass);
85
+ superklass = rb_class_superclass(superklass);
78
86
  if (superklass == rb_cObject)
79
87
  rb_raise(rb_eRuntimeError, "private method `new' called for %s:Class", rb_class2name(klass));
80
88
  }
@@ -10,7 +10,7 @@
10
10
  #include <errno.h>
11
11
  #include "oranumber_util.h"
12
12
 
13
- #ifndef RUBY_VM
13
+ #ifndef RB_NUM_COERCE_FUNCS_NEED_OPID
14
14
  /* ruby 1.8 */
15
15
  #define rb_num_coerce_cmp(x, y, id) rb_num_coerce_cmp((x), (y))
16
16
  #define rb_num_coerce_bin(x, y, id) rb_num_coerce_bin((x), (y))
@@ -39,6 +39,9 @@ static OCINumber const_mPI2; /* -PI/2 */
39
39
 
40
40
  #define _NUMBER(val) ((OCINumber *)DATA_PTR(val)) /* dangerous macro */
41
41
 
42
+ #ifndef T_MASK
43
+ #define T_MASK 0x100 /* TODO: rboci8_type() should be changed to be more portable. */
44
+ #endif
42
45
  #define RBOCI8_T_ORANUMBER (T_MASK + 1)
43
46
  #define RBOCI8_T_BIGDECIMAL (T_MASK + 2)
44
47
  #ifdef T_RATIONAL
@@ -721,13 +724,13 @@ static VALUE onum_add(VALUE lhs, VALUE rhs)
721
724
  oci_lc(OCINumberAdd(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
722
725
  return oci8_make_ocinumber(&r, errhp);
723
726
  case T_FLOAT:
724
- return rb_funcall(onum_to_f(lhs), '+', 1, rhs);
727
+ return rb_funcall(onum_to_f(lhs), oci8_id_add_op, 1, rhs);
725
728
  case RBOCI8_T_RATIONAL:
726
- return rb_funcall(onum_to_r(lhs), '+', 1, rhs);
729
+ return rb_funcall(onum_to_r(lhs), oci8_id_add_op, 1, rhs);
727
730
  case RBOCI8_T_BIGDECIMAL:
728
- return rb_funcall(onum_to_d(lhs), '+', 1, rhs);
731
+ return rb_funcall(onum_to_d(lhs), oci8_id_add_op, 1, rhs);
729
732
  }
730
- return rb_num_coerce_bin(lhs, rhs, '+');
733
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_add_op);
731
734
  }
732
735
 
733
736
  /*
@@ -755,13 +758,13 @@ static VALUE onum_sub(VALUE lhs, VALUE rhs)
755
758
  oci_lc(OCINumberSub(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
756
759
  return oci8_make_ocinumber(&r, errhp);
757
760
  case T_FLOAT:
758
- return rb_funcall(onum_to_f(lhs), '-', 1, rhs);
761
+ return rb_funcall(onum_to_f(lhs), oci8_id_sub_op, 1, rhs);
759
762
  case RBOCI8_T_RATIONAL:
760
- return rb_funcall(onum_to_r(lhs), '-', 1, rhs);
763
+ return rb_funcall(onum_to_r(lhs), oci8_id_sub_op, 1, rhs);
761
764
  case RBOCI8_T_BIGDECIMAL:
762
- return rb_funcall(onum_to_d(lhs), '-', 1, rhs);
765
+ return rb_funcall(onum_to_d(lhs), oci8_id_sub_op, 1, rhs);
763
766
  }
764
- return rb_num_coerce_bin(lhs, rhs, '-');
767
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_sub_op);
765
768
  }
766
769
 
767
770
  /*
@@ -788,13 +791,13 @@ static VALUE onum_mul(VALUE lhs, VALUE rhs)
788
791
  oci_lc(OCINumberMul(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
789
792
  return oci8_make_ocinumber(&r, errhp);
790
793
  case T_FLOAT:
791
- return rb_funcall(onum_to_f(lhs), '*', 1, rhs);
794
+ return rb_funcall(onum_to_f(lhs), oci8_id_mul_op, 1, rhs);
792
795
  case RBOCI8_T_RATIONAL:
793
- return rb_funcall(onum_to_r(lhs), '*', 1, rhs);
796
+ return rb_funcall(onum_to_r(lhs), oci8_id_mul_op, 1, rhs);
794
797
  case RBOCI8_T_BIGDECIMAL:
795
- return rb_funcall(onum_to_d(lhs), '*', 1, rhs);
798
+ return rb_funcall(onum_to_d(lhs), oci8_id_mul_op, 1, rhs);
796
799
  }
797
- return rb_num_coerce_bin(lhs, rhs, '*');
800
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_mul_op);
798
801
  }
799
802
 
800
803
  /*
@@ -830,13 +833,13 @@ static VALUE onum_div(VALUE lhs, VALUE rhs)
830
833
  oci_lc(OCINumberDiv(errhp, _NUMBER(lhs), _NUMBER(rhs), &r));
831
834
  return oci8_make_ocinumber(&r, errhp);
832
835
  case T_FLOAT:
833
- return rb_funcall(onum_to_f(lhs), '/', 1, rhs);
836
+ return rb_funcall(onum_to_f(lhs), oci8_id_div_op, 1, rhs);
834
837
  case RBOCI8_T_RATIONAL:
835
- return rb_funcall(onum_to_r(lhs), '/', 1, rhs);
838
+ return rb_funcall(onum_to_r(lhs), oci8_id_div_op, 1, rhs);
836
839
  case RBOCI8_T_BIGDECIMAL:
837
- return rb_funcall(onum_to_d(lhs), '/', 1, rhs);
840
+ return rb_funcall(onum_to_d(lhs), oci8_id_div_op, 1, rhs);
838
841
  }
839
- return rb_num_coerce_bin(lhs, rhs, '/');
842
+ return rb_num_coerce_bin(lhs, rhs, oci8_id_div_op);
840
843
  }
841
844
 
842
845
  /*
@@ -1171,7 +1174,7 @@ static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp)
1171
1174
  {
1172
1175
  char buf[64];
1173
1176
  ub4 buf_size = sizeof(buf);
1174
- const const char *fmt = "FM9.99999999999999999999999999999999999999EEEE";
1177
+ const char *fmt = "FM9.99999999999999999999999999999999999999EEEE";
1175
1178
 
1176
1179
  if (!cBigDecimal) {
1177
1180
  rb_require("bigdecimal");
@@ -1182,6 +1185,24 @@ static VALUE onum_to_d_real(OCINumber *num, OCIError *errhp)
1182
1185
  return rb_funcall(rb_cObject, id_BigDecimal, 1, rb_usascii_str_new(buf, buf_size));
1183
1186
  }
1184
1187
 
1188
+ /*
1189
+ * call-seq:
1190
+ * onum.has_decimal_part? -> true or false
1191
+ *
1192
+ * Returns +true+ if <i>self</i> has a decimal part.
1193
+ *
1194
+ * OraNumber(10).has_decimal_part? # => false
1195
+ * OraNumber(10.1).has_decimal_part? # => true
1196
+ */
1197
+ static VALUE onum_has_decimal_part_p(VALUE self)
1198
+ {
1199
+ OCIError *errhp = oci8_errhp;
1200
+ boolean result;
1201
+
1202
+ oci_lc(OCINumberIsInt(errhp, _NUMBER(self), &result));
1203
+ return result ? Qfalse : Qtrue;
1204
+ }
1205
+
1185
1206
  /*
1186
1207
  * call-seq:
1187
1208
  * onum.to_onum -> oranumber
@@ -1504,6 +1525,7 @@ Init_oci_number(VALUE cOCI8, OCIError *errhp)
1504
1525
  rb_define_method(cOCINumber, "to_f", onum_to_f, 0);
1505
1526
  rb_define_method(cOCINumber, "to_r", onum_to_r, 0);
1506
1527
  rb_define_method(cOCINumber, "to_d", onum_to_d, 0);
1528
+ rb_define_method(cOCINumber, "has_decimal_part?", onum_has_decimal_part_p, 0);
1507
1529
  rb_define_method_nodoc(cOCINumber, "to_onum", onum_to_onum, 0);
1508
1530
 
1509
1531
  rb_define_method(cOCINumber, "zero?", onum_zero_p, 0);
@@ -378,6 +378,18 @@ EOS
378
378
 
379
379
  private
380
380
 
381
+ def self.make_proc_to_check_cpu(expect)
382
+ Proc.new do |file|
383
+ so = MiniSOReader.new(file)
384
+ if so.cpu == expect
385
+ true
386
+ else
387
+ puts " skip: #{file} is for #{so.cpu} cpu."
388
+ false
389
+ end
390
+ end
391
+ end
392
+
381
393
  def self.check_ic_dir
382
394
  puts "checking for load library path... "
383
395
  STDOUT.flush
@@ -390,6 +402,16 @@ EOS
390
402
  so_ext = 'so'
391
403
  nls_data_ext = nil
392
404
  check_proc = nil
405
+ size_of_pointer = begin
406
+ # the size of a pointer.
407
+ [nil].pack('P').size
408
+ rescue ArgumentError
409
+ # Rubinius 1.2.3 doesn't support Array#pack('P').
410
+ # Use Fixnum#size, which returns the size of long.
411
+ 1.size
412
+ end
413
+ is_32bit = size_of_pointer == 4
414
+ is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102
393
415
  case RUBY_PLATFORM
394
416
  when /mswin32|cygwin|mingw32|bccwin32/
395
417
  oci_basename = 'oci'
@@ -398,40 +420,29 @@ EOS
398
420
  @@ld_envs = %w[PATH]
399
421
  so_ext = 'dll'
400
422
  when /i.86-linux/
401
- check_proc = Proc.new do |file|
402
- so = MiniSOReader.new(file)
403
- if so.cpu == :i386
404
- true
405
- else
406
- puts " skip: #{file} is for #{so.cpu} cpu."
407
- false
408
- end
409
- end
423
+ check_proc = make_proc_to_check_cpu(:i386)
410
424
  when /ia64-linux/
411
- check_proc = Proc.new do |file|
412
- so = MiniSOReader.new(file)
413
- if so.cpu == :ia64
414
- true
415
- else
416
- puts " skip: #{file} is for #{so.cpu} cpu."
417
- false
418
- end
419
- end
425
+ check_proc = make_proc_to_check_cpu(:ia64)
420
426
  when /x86_64-linux/
421
- check_proc = Proc.new do |file|
422
- so = MiniSOReader.new(file)
423
- if so.cpu == :x86_64
424
- true
427
+ # RUBY_PLATFORM depends on the compilation environment.
428
+ # Even though it is x86_64-linux, the compiled ruby may
429
+ # be a 32-bit executable.
430
+ check_proc = make_proc_to_check_cpu(is_32bit ? :i386 : :x86_64)
431
+ when /solaris/
432
+ if is_32bit
433
+ @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH]
434
+ if is_big_endian
435
+ check_proc = make_proc_to_check_cpu(:sparc)
425
436
  else
426
- puts " skip: #{file} is for #{so.cpu} cpu."
427
- false
437
+ check_proc = make_proc_to_check_cpu(:i386)
428
438
  end
429
- end
430
- when /solaris/
431
- if [0].pack('l!').length == 8
432
- @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH]
433
439
  else
434
- @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH]
440
+ @@ld_envs = %w[LD_LIBRARY_PATH_64 LD_LIBRARY_PATH]
441
+ if is_big_endian
442
+ check_proc = make_proc_to_check_cpu(:sparcv9)
443
+ else
444
+ check_proc = make_proc_to_check_cpu(:x86_64)
445
+ end
435
446
  end
436
447
  when /aix/
437
448
  oci_glob_postfix = ''
@@ -439,29 +450,27 @@ EOS
439
450
  so_ext = 'a'
440
451
  nls_data_ext = 'so'
441
452
  when /hppa.*-hpux/
442
- if [0].pack('l!').length == 4
453
+ if is_32bit
443
454
  @@ld_envs = %w[SHLIB_PATH]
444
455
  end
445
456
  so_ext = 'sl'
446
457
  when /darwin/
447
458
  @@ld_envs = %w[DYLD_LIBRARY_PATH]
448
459
  so_ext = 'dylib'
449
- check_proc = Proc.new do |file|
450
- is_32bit = [0].pack('l!').size == 4
451
- is_big_endian = "\x01\x02".unpack('s')[0] == 0x0102
452
- if is_32bit
453
- if is_big_endian
454
- this_cpu = :ppc # 32-bit big-endian
455
- else
456
- this_cpu = :i386 # 32-bit little-endian
457
- end
460
+ if is_32bit
461
+ if is_big_endian
462
+ this_cpu = :ppc # 32-bit big-endian
458
463
  else
459
- if is_big_endian
460
- this_cpu = :ppc64 # 64-bit big-endian
461
- else
462
- this_cpu = :x86_64 # 64-bit little-endian
463
- end
464
+ this_cpu = :i386 # 32-bit little-endian
464
465
  end
466
+ else
467
+ if is_big_endian
468
+ this_cpu = :ppc64 # 64-bit big-endian
469
+ else
470
+ this_cpu = :x86_64 # 64-bit little-endian
471
+ end
472
+ end
473
+ check_proc = Proc.new do |file|
465
474
  so = MiniSOReader.new(file)
466
475
  if so.file_format == :universal
467
476
  if so.cpu.include? this_cpu
@@ -495,40 +504,43 @@ EOS
495
504
  next
496
505
  end
497
506
  puts " #{env}... "
498
- ENV[env].split(File::PATH_SEPARATOR).each do |path|
499
- next if path.nil? or path == ''
500
- print " checking #{path}... "
501
- path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
502
- files = Dir.glob(File.join(path, glob_name))
503
- if files.empty?
504
- puts "no"
505
- next
506
- end
507
- STDOUT.flush
508
- next if (check_proc && !check_proc.call(files[0]))
509
- file = files[0]
510
- ld_path = path
511
- puts "yes"
512
- break
513
- end
514
- break
507
+ ld_path, file = check_lib_in_path(ENV[env], glob_name, check_proc)
508
+ break if ld_path
515
509
  end
516
510
 
517
- if ld_path.nil? and RUBY_PLATFORM =~ /linux/
518
- open("|/sbin/ldconfig -p") do |f|
519
- print " checking ld.so.conf... "
520
- STDOUT.flush
521
- while line = f.gets
522
- if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/
523
- file = "#$1/libclntsh.so.#$2"
524
- path = $1
525
- next if (check_proc && !check_proc.call(file))
526
- ld_path = path
527
- puts "yes"
528
- break
511
+ if ld_path.nil?
512
+ case RUBY_PLATFORM
513
+ when /linux/
514
+ open("|/sbin/ldconfig -p") do |f|
515
+ print " checking ld.so.conf... "
516
+ STDOUT.flush
517
+ while line = f.gets
518
+ if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/
519
+ file = "#$1/libclntsh.so.#$2"
520
+ path = $1
521
+ next if (check_proc && !check_proc.call(file))
522
+ ld_path = path
523
+ puts "yes"
524
+ break
525
+ end
526
+ end
527
+ puts "no"
528
+ end
529
+ when /solaris/
530
+ if is_32bit
531
+ crle_cmd = 'crle'
532
+ else
533
+ crle_cmd = 'crle -64'
534
+ end
535
+ open('|env LANG=C /usr/bin/' + crle_cmd) do |f|
536
+ while line = f.gets
537
+ if line =~ /Default Library Path[^:]*:\s*(\S*)/
538
+ puts " checking output of `#{crle_cmd}'... "
539
+ ld_path, file = check_lib_in_path($1, glob_name, check_proc)
540
+ break
541
+ end
529
542
  end
530
543
  end
531
- puts "no"
532
544
  end
533
545
  end
534
546
 
@@ -545,6 +557,23 @@ EOS
545
557
  nil
546
558
  end
547
559
 
560
+ def self.check_lib_in_path(paths, glob_name, check_proc)
561
+ paths.split(File::PATH_SEPARATOR).each do |path|
562
+ next if path.nil? or path == ''
563
+ print " checking #{path}... "
564
+ path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
565
+ files = Dir.glob(File.join(path, glob_name))
566
+ if files.empty?
567
+ puts "no"
568
+ next
569
+ end
570
+ STDOUT.flush
571
+ next if (check_proc && !check_proc.call(files[0]))
572
+ puts "yes"
573
+ return path, files[0]
574
+ end
575
+ end
576
+
548
577
  def init
549
578
  check_cc()
550
579
  @cc_is_gcc = check_cc_is_gcc()
@@ -1109,20 +1138,8 @@ EOS
1109
1138
  end
1110
1139
 
1111
1140
  if RUBY_PLATFORM =~ /darwin/
1112
- is_intelmac = ([1].pack('s') == "\001\000")
1113
- arch_ppc_error = false
1114
- arch_i386_error = false
1115
1141
  open('mkmf.log', 'r') do |f|
1116
1142
  while line = f.gets
1117
- # universal-darwin8.0 (Mac OS X 10.4?)
1118
- if line.include? 'cputype (18, architecture ppc) does not match cputype (7)'
1119
- # try to link an i386 library but the instant client is ppc.
1120
- arch_i386_error = true
1121
- end
1122
- if line.include? 'cputype (7, architecture i386) does not match cputype (18)'
1123
- # try to link a ppc library but the instant client is i386.
1124
- arch_ppc_error = true
1125
- end
1126
1143
  if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
1127
1144
  raise <<EOS
1128
1145
  Intel mac instant client is for Mac OS X 10.5.
@@ -1135,54 +1152,37 @@ You have three workarounds.
1135
1152
  EOS
1136
1153
  # '
1137
1154
  end
1138
- # universal-darwin9.0 (Mac OS X 10.5?)
1139
- if line.include? 'Undefined symbols for architecture i386:'
1140
- # try to link an i386 library but the instant client is ppc.
1141
- arch_i386_error = true
1142
- end
1143
- if line.include? 'Undefined symbols for architecture ppc:'
1144
- # try to link a ppc library but the instant client is i386.
1145
- arch_ppc_error = true
1155
+
1156
+ case line
1157
+ when /cputype \(\d+, architecture \w+\) does not match cputype \(\d+\) for specified -arch flag: (\w+)/
1158
+ missing_arch = $1
1159
+ when /Undefined symbols for architecture (\w+)/
1160
+ missing_arch = $1
1161
+ when /missing required architecture (\w+) in file/
1162
+ missing_arch = $1
1146
1163
  end
1147
1164
 
1148
- if arch_i386_error
1149
- if is_intelmac
1150
- # intel mac and '-arch i386' error
1151
- raise <<EOS
1152
- Could not compile with Oracle instant client.
1153
- Use intel mac instant client.
1154
- EOS
1165
+ if missing_arch
1166
+ if [nil].pack('p').size == 8
1167
+ my_arch = 'x86_64'
1168
+ elsif "\x01\x02".unpack('s')[0] == 0x0201
1169
+ my_arch = 'i386'
1155
1170
  else
1156
- # ppc mac and '-arch i386' error
1157
- raise <<EOS
1158
- Could not compile with Oracle instant client.
1159
- You may need to set a environment variable:
1160
- RC_ARCHS=ppc
1161
- export RC_ARCHS
1162
- If it does not fix the problem, delete all '-arch i386'
1163
- in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
1164
- EOS
1171
+ my_arch = 'ppc'
1165
1172
  end
1166
- end
1167
-
1168
- if arch_ppc_error
1169
- if is_intelmac
1170
- # intel mac and '-arch ppc' error
1171
- raise <<EOS
1173
+ raise <<EOS
1172
1174
  Could not compile with Oracle instant client.
1173
- You may need to set a environment variable:
1174
- RC_ARCHS=i386
1175
+ You may need to set the environment variable RC_ARCHS or ARCHFLAGS as follows:
1176
+
1177
+ RC_ARCHS=#{my_arch}
1178
+ export RC_ARCHS
1179
+ or
1180
+ ARCHFLAGS='-arch #{my_arch}'
1175
1181
  export RC_ARCHS
1176
- If it does not fix the problem, delete all '-arch ppc'
1182
+
1183
+ If it does not fix the problem, delete all '-arch #{missing_arch}'
1177
1184
  in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
1178
1185
  EOS
1179
- else
1180
- # ppc mac and '-arch ppc' error
1181
- raise <<EOS
1182
- Could not compile with Oracle instant client.
1183
- Use ppc instant client.
1184
- EOS
1185
- end
1186
1186
  end
1187
1187
  end
1188
1188
  end