ruby-oci8 2.0.6 → 2.1.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 (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
  }