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
@@ -1,35 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
- unless defined? macro_defined?
4
- # ruby 1.6 doesn't have 'macro_defined?'.
5
- def macro_defined?(macro, src, opt="")
6
- try_cpp(src + <<"SRC", opt)
7
- #ifndef #{macro}
8
- # error
9
- #endif
10
- SRC
11
- end
12
- end
13
-
14
- module Logging
15
- unless Logging.respond_to?(:open)
16
- # emulate Logging::open of ruby 1.6.8 or later.
17
-
18
- if $log.nil? # ruby 1.6.2 doesn't have $log.
19
- $log = open('mkmf.log', 'w')
20
- end
21
- def Logging::open
22
- begin
23
- $stderr.reopen($log)
24
- $stdout.reopen($log)
25
- yield
26
- ensure
27
- $stderr.reopen($orgerr)
28
- $stdout.reopen($orgout)
29
- end
30
- end
31
- end
32
- end # module Logging
3
+ # compatibility for ruby-1.9
4
+ RbConfig = Config unless defined? RbConfig
33
5
 
34
6
  module MiniRegistry
35
7
  class MiniRegistryError < StandardError
@@ -148,7 +120,7 @@ class MiniSOReader
148
120
  read_mach_o_unversal(f)
149
121
  else
150
122
  # AIX and Tru64
151
- raise format("unknown file header: %02x %02x", file_header[0], file_header[1])
123
+ raise format("unknown file header: %02x %02x", file_header[0].to_i, file_header[1].to_i)
152
124
  end
153
125
  ensure
154
126
  f.close
@@ -193,6 +165,8 @@ class MiniSOReader
193
165
  @cpu = :i386
194
166
  when 15
195
167
  @cpu = :parisc
168
+ when 18
169
+ @cpu = :sparc32plus
196
170
  when 20
197
171
  @cpu = :ppc
198
172
  when 21
@@ -378,10 +352,10 @@ EOS
378
352
 
379
353
  private
380
354
 
381
- def self.make_proc_to_check_cpu(expect)
355
+ def self.make_proc_to_check_cpu(*expect)
382
356
  Proc.new do |file|
383
357
  so = MiniSOReader.new(file)
384
- if so.cpu == expect
358
+ if expect.include? so.cpu
385
359
  true
386
360
  else
387
361
  puts " skip: #{file} is for #{so.cpu} cpu."
@@ -432,7 +406,7 @@ EOS
432
406
  if is_32bit
433
407
  @@ld_envs = %w[LD_LIBRARY_PATH_32 LD_LIBRARY_PATH]
434
408
  if is_big_endian
435
- check_proc = make_proc_to_check_cpu(:sparc)
409
+ check_proc = make_proc_to_check_cpu(:sparc, :sparc32plus)
436
410
  else
437
411
  check_proc = make_proc_to_check_cpu(:i386)
438
412
  end
@@ -572,12 +546,14 @@ EOS
572
546
  puts "yes"
573
547
  return path, files[0]
574
548
  end
549
+ nil
575
550
  end
576
551
 
577
552
  def init
578
553
  check_cc()
579
554
  @cc_is_gcc = check_cc_is_gcc()
580
555
  @lp64 = check_lp64()
556
+ check_system_header()
581
557
  check_ruby_header()
582
558
  end
583
559
 
@@ -619,33 +595,36 @@ EOS
619
595
  end
620
596
  end # check_lp64
621
597
 
598
+ def check_system_header
599
+ if not have_header('sys/types.h')
600
+ raise <<EOS
601
+ A standard C header file 'sys/types.h' doesn't exist.
602
+ Did you install glibc-devel(redhat) or libc6-dev(debian/ubuntu)?
603
+ EOS
604
+ end
605
+ end
606
+
622
607
  def check_ruby_header
623
608
  print "checking for ruby header... "
624
609
  STDOUT.flush
625
- rubyhdrdir = Config::CONFIG["rubyhdrdir"] || Config::CONFIG['archdir']
610
+ rubyhdrdir = RbConfig::CONFIG["rubyhdrdir"] || RbConfig::CONFIG['archdir']
626
611
  unless File.exist?(rubyhdrdir + '/ruby.h')
627
612
  puts "ng"
628
- if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{Config::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
613
+ if RUBY_PLATFORM =~ /darwin/ and File.exist?("#{RbConfig::CONFIG['archdir']}/../universal-darwin8.0/ruby.h")
629
614
  raise <<EOS
630
- #{Config::CONFIG['archdir']}/ruby.h doesn't exist.
615
+ #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
631
616
  Run the following commands to fix the problem.
632
617
 
633
- cd #{Config::CONFIG['archdir']}
618
+ cd #{RbConfig::CONFIG['archdir']}
634
619
  sudo ln -s ../universal-darwin8.0/* ./
635
620
  EOS
636
621
  else
637
622
  raise <<EOS
638
- #{Config::CONFIG['archdir']}/ruby.h doesn't exist.
623
+ #{RbConfig::CONFIG['archdir']}/ruby.h doesn't exist.
639
624
  Install the ruby development library.
640
625
  EOS
641
626
  end
642
627
  end
643
- if RUBY_PLATFORM =~ /linux/ and not File.exist?("/usr/include/sys/types.h")
644
- raise <<EOS
645
- Do you install glibc-devel(redhat) or libc6-dev(debian)?
646
- You need /usr/include/sys/types.h to compile ruby-oci8.
647
- EOS
648
- end
649
628
  puts "ok"
650
629
  $stdout.flush
651
630
  end # check_ruby_header
@@ -662,12 +641,12 @@ EOS
662
641
 
663
642
  if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/ # when Windows
664
643
 
665
- def get_libs(base_dir = oci_base_dir)
644
+ def get_libs(lib_dir)
666
645
  case RUBY_PLATFORM
667
646
  when /cygwin/
668
647
  open("OCI.def", "w") do |f|
669
648
  f.puts("EXPORTS")
670
- open("|nm #{base_dir}/LIB/MSVC/OCI.LIB") do |r|
649
+ open("|nm #{lib_dir}/MSVC/OCI.LIB") do |r|
671
650
  while line = r.gets
672
651
  f.puts($') if line =~ / T _/
673
652
  end
@@ -682,21 +661,34 @@ EOS
682
661
  when /bccwin32/
683
662
  # replace '/' to '\\' because bcc linker misunderstands
684
663
  # 'C:/foo/bar/OCI.LIB' as unknown option.
685
- lib = "#{base_dir}/LIB/BORLAND/OCI.LIB"
664
+ lib = "#{lib_dir}/BORLAND/OCI.LIB"
686
665
  return lib.tr('/', '\\') if File.exist?(lib)
687
666
  raise <<EOS
688
667
  #{lib} does not exist.
689
668
 
690
669
  Your Oracle may not support Borland C++.
691
670
  If you want to run this module, run the following command at your own risk.
692
- cd #{base_dir.tr('/', '\\')}\\LIB
671
+ cd #{lib_dir.tr('/', '\\')}
693
672
  mkdir Borland
694
673
  cd Borland
695
674
  coff2omf ..\\MSVC\\OCI.LIB OCI.LIB
696
675
  EOS
697
676
  exit 1
698
677
  else
699
- "\"#{base_dir}/LIB/MSVC/OCI.LIB\""
678
+ "\"#{lib_dir}/MSVC/OCI.LIB\""
679
+ end
680
+ end
681
+
682
+ else
683
+ # Unix
684
+ def get_libs(lib_dir)
685
+ case RUBY_PLATFORM
686
+ when /solaris/
687
+ " -L#{lib_dir} -R#{lib_dir} -lclntsh"
688
+ when /linux/
689
+ " -L#{lib_dir} -Wl,-rpath,#{lib_dir} -lclntsh"
690
+ else
691
+ " -L#{lib_dir} -lclntsh"
700
692
  end
701
693
  end
702
694
 
@@ -710,7 +702,7 @@ class OraConfFC < OraConf
710
702
 
711
703
  @oracle_home = get_home()
712
704
  if RUBY_PLATFORM =~ /freebsd/ && @oracle_home == '/usr/local/oracle8-client'
713
- @version = '817'
705
+ raise "Oralce 8i is not supported."
714
706
  else
715
707
  @version = get_version()
716
708
  end
@@ -725,34 +717,14 @@ class OraConfFC < OraConf
725
717
  use_lib32 = false
726
718
  end
727
719
 
728
- # default
729
- if @version.to_i >= 900
730
- if use_lib32
731
- lib_dir = "#{@oracle_home}/lib32"
732
- else
733
- lib_dir = "#{@oracle_home}/lib"
734
- end
735
- case RUBY_PLATFORM
736
- when /solaris/
737
- @libs = " -L#{lib_dir} -R#{lib_dir} -lclntsh"
738
- when /linux/
739
- @libs = " -L#{lib_dir} -Wl,-rpath,#{lib_dir} -lclntsh"
740
- else
741
- @libs = " -L#{lib_dir} -lclntsh"
742
- end
743
- return if try_link_oci()
744
- end
745
-
746
- # get from demo_rdbms.mk
747
- if use_lib32
748
- if File.exist?("#{@oracle_home}/rdbms/demo/demo_rdbms32.mk")
749
- @libs = get_libs('32', '')
750
- else
751
- @libs = get_libs('', '32')
752
- end
720
+ if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
721
+ lib_dir = "#{@oracle_home}/oci/lib"
722
+ elsif use_lib32
723
+ lib_dir = "#{@oracle_home}/lib32"
753
724
  else
754
- @libs = get_libs()
725
+ lib_dir = "#{@oracle_home}/lib"
755
726
  end
727
+ @libs = get_libs(lib_dir)
756
728
  return if try_link_oci()
757
729
 
758
730
  raise 'cannot compile OCI'
@@ -870,23 +842,14 @@ EOS
870
842
  oracle_home.gsub(/\\/, '/')
871
843
  end
872
844
 
873
- def oci_base_dir
874
- case @version
875
- when /80./
876
- "#{@oracle_home}/OCI80"
877
- else
878
- "#{@oracle_home}/OCI"
879
- end
880
- end
881
-
882
845
  def get_cflags
883
- unless File.exist?("#{oci_base_dir}/INCLUDE/OCI.H")
884
- raise "'#{oci_base_dir}/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
846
+ unless File.exist?("#{@oracle_home}/OCI/INCLUDE/OCI.H")
847
+ raise "'#{@oracle_home}/OCI/INCLUDE/OCI.H' does not exists. Please install 'Oracle Call Interface'."
885
848
  end
886
849
  if RUBY_PLATFORM =~ /cygwin/
887
- " \"-I#{oci_base_dir}/INCLUDE\" -D_int64=\"long long\""
850
+ " \"-I#{@oracle_home}/OCI/INCLUDE\" -D_int64=\"long long\""
888
851
  else
889
- " \"-I#{oci_base_dir}/INCLUDE\""
852
+ " \"-I#{@oracle_home}/OCI/INCLUDE\""
890
853
  end
891
854
  end
892
855
 
@@ -957,70 +920,6 @@ EOS
957
920
  end
958
921
  end # get_cflags
959
922
 
960
- def get_libs(postfix1 = '', postfix2 = "")
961
- print("Running make for $ORACLE_HOME/rdbms/demo/demo_rdbms#{postfix1}.mk (build#{postfix2}) ...")
962
- STDOUT.flush
963
-
964
- make_opt = "CC='echo MARKER' EXE=/dev/null ECHODO=echo ECHO=echo GENCLNTSH='echo genclntsh'"
965
- if @cc_is_gcc && /solaris/ =~ RUBY_PLATFORM
966
- # suggested by Brian Candler.
967
- make_opt += " KPIC_OPTION= NOKPIC_CCFLAGS#{postfix2}="
968
- end
969
-
970
- command = "|make -f #{@oracle_home}/rdbms/demo/demo_rdbms#{postfix1}.mk build#{postfix2} #{make_opt}"
971
- marker = /^\s*MARKER/
972
- echo = /^\s*echo/
973
- libs = nil
974
- Logging::open do
975
- puts command
976
- open(command, "r") do |f|
977
- while line = f.gets
978
- puts line
979
- line.chomp!
980
- line = $' while line =~ echo
981
- if line =~ marker
982
- # found a line where a compiler runs.
983
- libs = $'
984
- libs.gsub!(/-o\s+\/dev\/null/, "")
985
- libs.gsub!(/-o\s+build/, "")
986
- end
987
- end
988
- end
989
- end
990
- raise 'Cannot get proper libs.' if libs.nil?
991
- print("OK\n")
992
-
993
- case RUBY_PLATFORM
994
- when /hpux/
995
- if @cc_is_gcc
996
- # strip +DA2.0W, +DS2.0, -Wl,+s, -Wl,+n
997
- libs.gsub!(/\+DA\S+(\s)*/, "")
998
- libs.gsub!(/\+DS\S+(\s)*/, "")
999
- libs.gsub!(/-Wl,\+[sn](\s)*/, "")
1000
- end
1001
- libs.gsub!(/ -Wl,/, " ")
1002
- when /aix/
1003
- if @cc_is_gcc
1004
- # strip -bI:/xxx
1005
- libs.gsub!(/(-bI:\S+)/, '')
1006
- end
1007
- end
1008
-
1009
- # check whether object files are included.
1010
- if /\S+\.o\b/ =~ libs
1011
-
1012
- # monkey patching!
1013
- Object.module_eval do
1014
- alias :link_command_pre_oci8 :link_command
1015
- def link_command(*args)
1016
- args[1] = "" if args[1] == $libs
1017
- link_command_pre_oci8(*args)
1018
- end
1019
- end
1020
-
1021
- end
1022
- libs
1023
- end # get_libs
1024
923
  end
1025
924
  end
1026
925
 
@@ -1072,7 +971,7 @@ EOS
1072
971
  end
1073
972
  @cflags = " \"-I#{inc_dir}\""
1074
973
  @cflags += " -D_int64=\"long long\"" if RUBY_PLATFORM =~ /cygwin/
1075
- @libs = get_libs("#{ic_dir}/sdk")
974
+ @libs = get_libs("#{ic_dir}/sdk/lib")
1076
975
  ld_path = nil
1077
976
  else
1078
977
  @cflags = " -I#{inc_dir}"
@@ -1116,7 +1015,7 @@ EOS
1116
1015
  end
1117
1016
  raise 'failed'
1118
1017
  end
1119
- @libs = " -L#{lib_dir} -lclntsh "
1018
+ @libs = get_libs(lib_dir)
1120
1019
  end
1121
1020
  unless File.exist?("#{inc_dir}/oci.h")
1122
1021
  raise <<EOS
@@ -1133,6 +1032,18 @@ EOS
1133
1032
  else
1134
1033
  # 10.1.0 doesn't have OCI_MAJOR_VERSION and OCI_MINOR_VERSION in oci.h.
1135
1034
  @version = "1010"
1035
+ if RUBY_PLATFORM =~ /darwin/ and 1.size == 8 and `sw_vers -productVersion`.chomp == "10.7"
1036
+ $stderr.print <<EOS
1037
+ WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1038
+
1039
+ 64-bit Oracle instant client doesn't work on OS X Lion.
1040
+ See: https://forums.oracle.com/forums/thread.jspa?threadID=2187558
1041
+
1042
+ The compilation is continued because the issue may be fixed in future.
1043
+
1044
+ WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN! WARN!
1045
+ EOS
1046
+ end
1136
1047
  end
1137
1048
  return
1138
1049
  end
@@ -1181,7 +1092,7 @@ or
1181
1092
  export RC_ARCHS
1182
1093
 
1183
1094
  If it does not fix the problem, delete all '-arch #{missing_arch}'
1184
- in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
1095
+ in '#{RbConfig::CONFIG['archdir']}/rbconfig.rb'.
1185
1096
  EOS
1186
1097
  end
1187
1098
  end
@@ -2,9 +2,6 @@
2
2
  /*
3
3
  * oradate.c
4
4
  *
5
- * $Author: kubo $
6
- * $Date: 2010-09-05 22:07:21 +0900 (Sun, 05 Sep 2010) $
7
- *
8
5
  * Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
9
6
  *
10
7
  * date and time between 4712 B.C. and 9999 A.D.
@@ -557,7 +554,7 @@ static void bind_oradate_init_elem(oci8_bind_t *obind, VALUE svc)
557
554
  } while (++idx < obind->maxar_sz);
558
555
  }
559
556
 
560
- static const oci8_bind_class_t bind_oradate_class = {
557
+ static const oci8_bind_vtable_t bind_oradate_vtable = {
561
558
  {
562
559
  NULL,
563
560
  oci8_bind_free,
@@ -568,8 +565,6 @@ static const oci8_bind_class_t bind_oradate_class = {
568
565
  bind_oradate_init,
569
566
  bind_oradate_init_elem,
570
567
  NULL,
571
- NULL,
572
- NULL,
573
568
  SQLT_DAT,
574
569
  };
575
570
 
@@ -612,5 +607,5 @@ void Init_ora_date(void)
612
607
  rb_define_method(cOraDate, "_dump", ora_date_dump, -1);
613
608
  rb_define_singleton_method(cOraDate, "_load", ora_date_s_load, 1);
614
609
 
615
- oci8_define_bind_class("OraDate", &bind_oradate_class);
610
+ oci8_define_bind_class("OraDate", &bind_oradate_vtable);
616
611
  }
@@ -53,7 +53,7 @@ static void oci8_stmt_free(oci8_base_t *base)
53
53
  stmt->defns = Qnil;
54
54
  }
55
55
 
56
- static oci8_base_class_t oci8_stmt_class = {
56
+ static oci8_base_vtable_t oci8_stmt_vtable = {
57
57
  oci8_stmt_mark,
58
58
  oci8_stmt_free,
59
59
  sizeof(oci8_stmt_t),
@@ -87,7 +87,7 @@ static VALUE oci8_stmt_initialize(int argc, VALUE *argv, VALUE self)
87
87
  if (argc > 1) {
88
88
  rv = OCIStmtPrepare(stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
89
89
  if (IS_OCI_ERROR(rv)) {
90
- oci8_raise(oci8_errhp, rv, stmt->base.hp.stmt);
90
+ chker3(rv, &stmt->base, stmt->base.hp.stmt);
91
91
  }
92
92
  }
93
93
  oci8_link_to_parent((oci8_base_t*)stmt, (oci8_base_t*)DATA_PTR(svc));
@@ -99,24 +99,18 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
99
99
  oci8_stmt_t *stmt = TO_STMT(self);
100
100
  ub4 position;
101
101
  oci8_bind_t *obind;
102
- const oci8_bind_class_t *bind_class;
102
+ const oci8_bind_vtable_t *vptr;
103
103
  sword status;
104
- ub4 mode;
105
104
 
106
105
  position = NUM2INT(vposition); /* 1 */
107
106
  obind = oci8_get_bind(vbindobj); /* 2 */
108
107
  if (obind->base.hp.dfn != NULL) {
109
108
  oci8_base_free(&obind->base); /* TODO: OK? */
110
109
  }
111
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
112
- if (bind_class->out == NULL) {
113
- mode = OCI_DEFAULT;
114
- } else {
115
- mode = OCI_DYNAMIC_FETCH;
116
- }
117
- status = OCIDefineByPos(stmt->base.hp.stmt, &obind->base.hp.dfn, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, NIL_P(obind->tdo) ? obind->u.inds : NULL, NULL, 0, mode);
110
+ vptr = (const oci8_bind_vtable_t *)obind->base.vptr;
111
+ status = OCIDefineByPos(stmt->base.hp.stmt, &obind->base.hp.dfn, oci8_errhp, position, obind->valuep, obind->value_sz, vptr->dty, NIL_P(obind->tdo) ? obind->u.inds : NULL, NULL, 0, OCI_DEFAULT);
118
112
  if (status != OCI_SUCCESS) {
119
- oci8_raise(oci8_errhp, status, stmt->base.hp.ptr);
113
+ chker3(status, &stmt->base, stmt->base.hp.ptr);
120
114
  }
121
115
  obind->base.type = OCI_HTYPE_DEFINE;
122
116
  /* link to the parent as soon as possible to preserve deallocation order. */
@@ -124,12 +118,10 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
124
118
  oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
125
119
 
126
120
  if (NIL_P(obind->tdo) && obind->maxar_sz > 0) {
127
- oci_lc(OCIDefineArrayOfStruct(obind->base.hp.dfn, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0));
121
+ chker2(OCIDefineArrayOfStruct(obind->base.hp.dfn, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0), &stmt->base);
128
122
  }
129
- if (RTEST(obind->tdo)) {
130
- oci8_base_t *tdo = DATA_PTR(obind->tdo);
131
- oci_lc(OCIDefineObject(obind->base.hp.dfn, oci8_errhp, tdo->hp.tdo,
132
- obind->valuep, 0, obind->u.null_structs, 0));
123
+ if (vptr->post_bind_hook != NULL) {
124
+ vptr->post_bind_hook(obind);
133
125
  }
134
126
  if (position - 1 < RARRAY_LEN(stmt->defns)) {
135
127
  VALUE old_value = RARRAY_PTR(stmt->defns)[position - 1];
@@ -137,9 +129,6 @@ static VALUE oci8_define_by_pos(VALUE self, VALUE vposition, VALUE vbindobj)
137
129
  oci8_base_free((oci8_base_t*)oci8_get_bind(old_value));
138
130
  }
139
131
  }
140
- if (bind_class->csfrm != 0) {
141
- oci_lc(OCIAttrSet(obind->base.hp.ptr, OCI_HTYPE_DEFINE, (void*)&bind_class->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp));
142
- }
143
132
  rb_ary_store(stmt->defns, position - 1, obind->base.self);
144
133
  return obind->base.self;
145
134
  }
@@ -151,12 +140,10 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
151
140
  ub4 placeholder_len = 0;
152
141
  ub4 position = 0;
153
142
  oci8_bind_t *obind;
154
- const oci8_bind_class_t *bind_class;
143
+ const oci8_bind_vtable_t *vptr;
155
144
  sword status;
156
145
  VALUE old_value;
157
146
  void *indp;
158
- ub4 *curelep;
159
- ub4 mode;
160
147
 
161
148
  if (NIL_P(vplaceholder)) { /* 1 */
162
149
  placeholder_ptr = NULL;
@@ -179,26 +166,16 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
179
166
  if (obind->base.hp.bnd != NULL) {
180
167
  oci8_base_free(&obind->base); /* TODO: OK? */
181
168
  }
182
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
183
- if (bind_class->in != NULL || bind_class->out != NULL) {
184
- mode = OCI_DATA_AT_EXEC;
185
- } else {
186
- mode = OCI_DEFAULT;
187
- }
169
+ vptr = (const oci8_bind_vtable_t *)obind->base.vptr;
188
170
 
189
171
  indp = NIL_P(obind->tdo) ? obind->u.inds : NULL;
190
- if (obind->maxar_sz == 0) {
191
- curelep = NULL;
192
- } else {
193
- curelep = &obind->curar_sz;
194
- }
195
172
  if (placeholder_ptr == (char*)-1) {
196
- status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, mode);
173
+ status = OCIBindByPos(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, position, obind->valuep, obind->value_sz, vptr->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT);
197
174
  } else {
198
- status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, bind_class->dty, indp, NULL, 0, 0, 0, mode);
175
+ status = OCIBindByName(stmt->base.hp.stmt, &obind->base.hp.bnd, oci8_errhp, TO_ORATEXT(placeholder_ptr), placeholder_len, obind->valuep, obind->value_sz, vptr->dty, indp, NULL, 0, 0, 0, OCI_DEFAULT);
199
176
  }
200
177
  if (status != OCI_SUCCESS) {
201
- oci8_raise(oci8_errhp, status, stmt->base.hp.stmt);
178
+ chker3(status, &stmt->base, stmt->base.hp.stmt);
202
179
  }
203
180
  obind->base.type = OCI_HTYPE_BIND;
204
181
  /* link to the parent as soon as possible to preserve deallocation order. */
@@ -206,15 +183,11 @@ static VALUE oci8_bind(VALUE self, VALUE vplaceholder, VALUE vbindobj)
206
183
  oci8_link_to_parent((oci8_base_t*)obind, (oci8_base_t*)stmt);
207
184
 
208
185
  if (NIL_P(obind->tdo) && obind->maxar_sz > 0) {
209
- oci_lc(OCIBindArrayOfStruct(obind->base.hp.bnd, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0));
186
+ chker2(OCIBindArrayOfStruct(obind->base.hp.bnd, oci8_errhp, obind->alloc_sz, sizeof(sb2), 0, 0),
187
+ &stmt->base);
210
188
  }
211
- if (!NIL_P(obind->tdo)) {
212
- oci8_base_t *tdo = DATA_PTR(obind->tdo);
213
- oci_lc(OCIBindObject(obind->base.hp.bnd, oci8_errhp, tdo->hp.tdo,
214
- obind->valuep, 0, obind->u.null_structs, 0));
215
- }
216
- if (bind_class->csfrm != 0) {
217
- oci_lc(OCIAttrSet(obind->base.hp.ptr, OCI_HTYPE_BIND, (void*)&bind_class->csfrm, 0, OCI_ATTR_CHARSET_FORM, oci8_errhp));
189
+ if (vptr->post_bind_hook != NULL) {
190
+ vptr->post_bind_hook(obind);
218
191
  }
219
192
  old_value = rb_hash_aref(stmt->binds, vplaceholder);
220
193
  if (!NIL_P(old_value)) {
@@ -247,9 +220,8 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
247
220
  oci8_svcctx_t *svcctx = oci8_get_svcctx(stmt->svc);
248
221
  ub4 iters;
249
222
  ub4 mode;
250
- sword rv;
251
223
 
252
- if (oci8_get_ub2_attr(&stmt->base, OCI_ATTR_STMT_TYPE) == INT2FIX(OCI_STMT_SELECT)) {
224
+ if (oci8_get_ub2_attr(&stmt->base, OCI_ATTR_STMT_TYPE, stmt->base.hp.stmt) == INT2FIX(OCI_STMT_SELECT)) {
253
225
  iters = 0;
254
226
  mode = OCI_DEFAULT;
255
227
  } else {
@@ -259,58 +231,8 @@ static VALUE oci8_stmt_execute(VALUE self, VALUE iteration_count)
259
231
  iters = 1;
260
232
  mode = svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
261
233
  }
262
- rv = oci8_call_stmt_execute(svcctx, stmt, iters, mode);
263
- #ifdef USE_DYNAMIC_FETCH
264
- while (rv == OCI_NEED_DATA) {
265
- oci8_bind_t *obind;
266
- const oci8_bind_class_t *bind_class;
267
- /* get piece info. */
268
- dvoid *hp;
269
- ub4 type;
270
- ub1 in_out;
271
- ub4 iter;
272
- ub4 idx;
273
- ub1 piece;
274
- /* set piece info. */
275
- void *valuep;
276
- ub4 *alenp;
277
- void *indp;
278
-
279
- oci_lc(OCIStmtGetPieceInfo(stmt->base.hp.ptr, oci8_errhp, &hp, &type, &in_out, &iter, &idx, &piece));
280
- obind = (oci8_bind_t*)stmt->base.children;
281
- do {
282
- if (obind->base.hp.ptr == hp) {
283
- if (type != OCI_HTYPE_BIND)
284
- rb_bug("ruby-oci8: expect OCI_HTYPE_BIND but %d", type);
285
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
286
- switch (in_out) {
287
- case OCI_PARAM_IN:
288
- if (bind_class->in == NULL)
289
- rb_bug("....");
290
- piece = bind_class->in(obind, idx, piece, &valuep, &alenp, &indp);
291
- break;
292
- case OCI_PARAM_OUT:
293
- if (bind_class->out == NULL)
294
- rb_bug("....");
295
- bind_class->out(obind, idx, piece, &valuep, &alenp, &indp);
296
- break;
297
- default:
298
- rb_bug("ruby-oci8: expect OCI_PARAM_IN or OCI_PARAM_OUT but %d", in_out);
299
- }
300
- oci_lc(OCIStmtSetPieceInfo(obind->base.hp.ptr, OCI_HTYPE_BIND, oci8_errhp, valuep, alenp, 0, indp, NULL));
301
- break;
302
- }
303
- obind = (oci8_bind_t*)obind->base.next;
304
- } while (obind != (oci8_bind_t*)stmt->base.children);
305
- if (obind == (oci8_bind_t*)stmt) {
306
- rb_bug("ruby-oci8: No bind handle is found.");
307
- }
308
- rv = oci8_call_stmt_execute(svcctx, stmt, iters, mode);
309
- }
310
- #endif /* USE_DYNAMIC_FETCH */
311
- if (IS_OCI_ERROR(rv)) {
312
- oci8_raise(oci8_errhp, rv, stmt->base.hp.stmt);
313
- }
234
+ chker3(oci8_call_stmt_execute(svcctx, stmt, iters, mode),
235
+ &stmt->base, stmt->base.hp.stmt);
314
236
  return self;
315
237
  }
316
238
 
@@ -346,93 +268,25 @@ static VALUE oci8_stmt_do_fetch(oci8_stmt_t *stmt, oci8_svcctx_t *svcctx)
346
268
  sword rv;
347
269
  long idx;
348
270
  oci8_bind_t *obind;
349
- const oci8_bind_class_t *bind_class;
271
+ const oci8_bind_vtable_t *vptr;
350
272
 
351
273
  if (stmt->base.children != NULL) {
352
274
  obind = (oci8_bind_t *)stmt->base.children;
353
275
  do {
354
276
  if (obind->base.type == OCI_HTYPE_DEFINE) {
355
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
356
- if (bind_class->pre_fetch_hook != NULL) {
357
- bind_class->pre_fetch_hook(obind, stmt->svc);
277
+ vptr = (const oci8_bind_vtable_t *)obind->base.vptr;
278
+ if (vptr->pre_fetch_hook != NULL) {
279
+ vptr->pre_fetch_hook(obind, stmt->svc);
358
280
  }
359
281
  }
360
282
  obind = (oci8_bind_t *)obind->base.next;
361
283
  } while (obind != (oci8_bind_t*)stmt->base.children);
362
284
  }
363
285
  rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
364
- #ifdef USE_DYNAMIC_FETCH
365
- while (rv == OCI_NEED_DATA) {
366
- /* get piece info. */
367
- dvoid *hp;
368
- ub4 type;
369
- ub1 in_out;
370
- ub4 iter;
371
- ub4 idx;
372
- ub1 piece;
373
- /* set piece info. */
374
- void *valuep;
375
- ub4 *alenp;
376
- void *indp;
377
-
378
- oci_lc(OCIStmtGetPieceInfo(stmt->base.hp.ptr, oci8_errhp, &hp, &type, &in_out, &iter, &idx, &piece));
379
- obind = (oci8_bind_t *)stmt->base.children;
380
- do {
381
- if (obind->base.hp.ptr == hp) {
382
- if (type != OCI_HTYPE_DEFINE)
383
- rb_bug("ruby-oci8: expect OCI_HTYPE_DEFINE but %d", type);
384
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
385
- switch (in_out) {
386
- case OCI_PARAM_OUT:
387
- if (bind_class->out == NULL)
388
- rb_bug("....");
389
- bind_class->out(obind, idx, piece, &valuep, &alenp, &indp);
390
- break;
391
- default:
392
- rb_bug("ruby-oci8: expect OCI_PARAM_OUT but %d", in_out);
393
- }
394
- oci_lc(OCIStmtSetPieceInfo(obind->base.hp.ptr, OCI_HTYPE_DEFINE, oci8_errhp, valuep, alenp, 0, indp, NULL));
395
- break;
396
- }
397
- obind = (oci8_bind_t *)obind->base.next;
398
- } while (obind != (oci8_bind_t*)stmt->base.children);
399
- if (obind == (oci8_bind_t*)stmt) {
400
- rb_bug("ruby-oci8: No define handle is found.");
401
- }
402
- rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
403
- }
404
- #endif /* USE_DYNAMIC_FETCH */
405
286
  if (rv == OCI_NO_DATA) {
406
287
  return Qnil;
407
288
  }
408
- if (IS_OCI_ERROR(rv)) {
409
- oci8_raise(oci8_errhp, rv, stmt->base.hp.stmt);
410
- }
411
- #ifdef USE_DYNAMIC_FETCH
412
- obind = (oci8_bind_t *)stmt->base.children;
413
- do {
414
- /* set piece info. */
415
- void *valuep;
416
- ub4 *alenp;
417
- void *indp;
418
- ub1 piece = OCI_LAST_PIECE;
419
-
420
- if (obind->base.type == OCI_HTYPE_DEFINE) {
421
- bind_class = (const oci8_bind_class_t *)obind->base.klass;
422
- if (bind_class->out != NULL) {
423
- if (obind->maxar_sz == 0) {
424
- bind_class->out(obind, 0, piece, &valuep, &alenp, &indp);
425
- } else {
426
- ub4 idx;
427
- for (idx = 0; idx < obind->curar_sz; idx++) {
428
- bind_class->out(obind, idx, piece, &valuep, &alenp, &indp);
429
- }
430
- }
431
- }
432
- }
433
- obind = (oci8_bind_t *)obind->base.next;
434
- } while (obind != (oci8_bind_t*)stmt->base.children);
435
- #endif /* USE_DYNAMIC_FETCH */
289
+ chker3(rv, &svcctx->base, stmt->base.hp.stmt);
436
290
  ary = rb_ary_new2(RARRAY_LEN(stmt->defns));
437
291
  for (idx = 0; idx < RARRAY_LEN(stmt->defns); idx++) {
438
292
  rb_ary_store(ary, idx, oci8_bind_get_data(RARRAY_PTR(stmt->defns)[idx]));
@@ -479,7 +333,7 @@ static VALUE oci8_stmt_get_param(VALUE self, VALUE pos)
479
333
  Check_Type(pos, T_FIXNUM); /* 1 */
480
334
  rv = OCIParamGet(stmt->base.hp.stmt, OCI_HTYPE_STMT, oci8_errhp, (dvoid *)&parmhp, FIX2INT(pos));
481
335
  if (rv != OCI_SUCCESS) {
482
- oci8_raise(oci8_errhp, rv, NULL);
336
+ chker3(rv, &stmt->base, stmt->base.hp.stmt);
483
337
  }
484
338
  return oci8_metadata_create(parmhp, stmt->svc, self);
485
339
  }
@@ -504,7 +358,8 @@ static VALUE oci8_stmt_get_param(VALUE self, VALUE pos)
504
358
  */
505
359
  static VALUE oci8_stmt_get_stmt_type(VALUE self)
506
360
  {
507
- VALUE stmt_type = oci8_get_ub2_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_STMT_TYPE);
361
+ oci8_base_t *base = oci8_get_handle(self, cOCIStmt);
362
+ VALUE stmt_type = oci8_get_ub2_attr(base, OCI_ATTR_STMT_TYPE, base->hp.stmt);
508
363
  switch (FIX2INT(stmt_type)) {
509
364
  case OCI_STMT_SELECT:
510
365
  return oci8_sym_select_stmt;
@@ -534,7 +389,8 @@ static VALUE oci8_stmt_get_stmt_type(VALUE self)
534
389
  */
535
390
  static VALUE oci8_stmt_get_row_count(VALUE self)
536
391
  {
537
- return oci8_get_ub4_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_ROW_COUNT);
392
+ oci8_base_t *base = oci8_get_handle(self, cOCIStmt);
393
+ return oci8_get_ub4_attr(base, OCI_ATTR_ROW_COUNT, base->hp.stmt);
538
394
  }
539
395
 
540
396
  /*
@@ -553,12 +409,14 @@ static VALUE oci8_stmt_get_row_count(VALUE self)
553
409
  */
554
410
  static VALUE oci8_stmt_get_rowid(VALUE self)
555
411
  {
556
- return oci8_get_rowid_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_ROWID);
412
+ oci8_base_t *base = oci8_get_handle(self, cOCIStmt);
413
+ return oci8_get_rowid_attr(base, OCI_ATTR_ROWID, base->hp.stmt);
557
414
  }
558
415
 
559
416
  static VALUE oci8_stmt_get_param_count(VALUE self)
560
417
  {
561
- return oci8_get_ub4_attr(oci8_get_handle(self, cOCIStmt), OCI_ATTR_PARAM_COUNT);
418
+ oci8_base_t *base = oci8_get_handle(self, cOCIStmt);
419
+ return oci8_get_ub4_attr(base, OCI_ATTR_PARAM_COUNT, base->hp.stmt);
562
420
  }
563
421
 
564
422
  /*
@@ -702,7 +560,8 @@ static VALUE oci8_stmt_set_prefetch_rows(VALUE self, VALUE rows)
702
560
  oci8_stmt_t *stmt = TO_STMT(self);
703
561
  ub4 num = NUM2UINT(rows);
704
562
 
705
- oci_lc(OCIAttrSet(stmt->base.hp.ptr, OCI_HTYPE_STMT, &num, 0, OCI_ATTR_PREFETCH_ROWS, oci8_errhp));
563
+ chker2(OCIAttrSet(stmt->base.hp.ptr, OCI_HTYPE_STMT, &num, 0, OCI_ATTR_PREFETCH_ROWS, oci8_errhp),
564
+ &stmt->base);
706
565
  return Qfalse;
707
566
  }
708
567
 
@@ -746,7 +605,7 @@ static void bind_stmt_init_elem(oci8_bind_t *obind, VALUE svc)
746
605
  } while (++idx < obind->maxar_sz);
747
606
  }
748
607
 
749
- static const oci8_bind_class_t bind_stmt_class = {
608
+ static const oci8_bind_vtable_t bind_stmt_vtable = {
750
609
  {
751
610
  oci8_bind_hp_obj_mark,
752
611
  oci8_bind_free,
@@ -756,8 +615,6 @@ static const oci8_bind_class_t bind_stmt_class = {
756
615
  bind_stmt_set,
757
616
  bind_stmt_init,
758
617
  bind_stmt_init_elem,
759
- NULL,
760
- NULL,
761
618
  bind_stmt_init_elem,
762
619
  SQLT_RSET
763
620
  };
@@ -769,7 +626,7 @@ void Init_oci8_stmt(VALUE cOCI8)
769
626
  cOCI8 = rb_define_class("OCI8", cOCIHandle);
770
627
  cOCIStmt = rb_define_class_under(cOCI8, "Cursor", cOCIHandle);
771
628
  #endif
772
- cOCIStmt = oci8_define_class_under(cOCI8, "Cursor", &oci8_stmt_class);
629
+ cOCIStmt = oci8_define_class_under(cOCI8, "Cursor", &oci8_stmt_vtable);
773
630
 
774
631
  oci8_sym_select_stmt = ID2SYM(rb_intern("select_stmt"));
775
632
  oci8_sym_update_stmt = ID2SYM(rb_intern("update_stmt"));
@@ -806,5 +663,5 @@ void Init_oci8_stmt(VALUE cOCI8)
806
663
  rb_define_private_method(cOCIStmt, "__defined?", oci8_stmt_defined_p, 1);
807
664
  rb_define_method(cOCIStmt, "prefetch_rows=", oci8_stmt_set_prefetch_rows, 1);
808
665
 
809
- oci8_define_bind_class("Cursor", &bind_stmt_class);
666
+ oci8_define_bind_class("Cursor", &bind_stmt_vtable);
810
667
  }