[ruby-oci8-commit] [267] trunk/ruby-oci8: * ext/oci8/oraconf.rb:

nobody at rubyforge.org nobody at rubyforge.org
Sat Jul 5 10:50:50 EDT 2008


Revision: 267
Author:   kubo
Date:     2008-07-05 10:50:50 -0400 (Sat, 05 Jul 2008)

Log Message:
-----------
* ext/oci8/oraconf.rb:
   1. prints more information on checking LD_LIBRARY_PATH.
   2. fix for windows Oracle 11g instant client.
   3. fix for intel mac instant client.
* ext/oci8/object.c, lib/oci8/object.rb, lib/oci8/oci8.rb:
   fix to pass an array of Oracle objects to a procedure.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/object.c
    trunk/ruby-oci8/ext/oci8/oraconf.rb
    trunk/ruby-oci8/lib/oci8/object.rb
    trunk/ruby-oci8/lib/oci8/oci8.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2008-07-05 14:31:24 UTC (rev 266)
+++ trunk/ruby-oci8/ChangeLog	2008-07-05 14:50:50 UTC (rev 267)
@@ -1,3 +1,11 @@
+2008-07-05  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/oraconf.rb:
+	   1. prints more information on checking LD_LIBRARY_PATH.
+	   2. fix for windows Oracle 11g instant client.
+	   3. fix for intel mac instant client.
+	* ext/oci8/object.c, lib/oci8/object.rb, lib/oci8/oci8.rb:
+	   fix to pass an array of Oracle objects to a procedure.
+
 2008-04-27  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/stmt.c, lib/oci8/oci8.rb: fix typo.
 	    (pointed by Liming)

Modified: trunk/ruby-oci8/ext/oci8/object.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/object.c	2008-07-05 14:31:24 UTC (rev 266)
+++ trunk/ruby-oci8/ext/oci8/object.c	2008-07-05 14:50:50 UTC (rev 267)
@@ -251,6 +251,8 @@
         double dbl;
         float flt;
     } data;
+    OCIInd ind; /* for data.num, data.dbl, data.flt */
+    OCIInd *indp;
 } set_coll_element_cb_data_t;
 
 static VALUE set_coll_element_func(set_coll_element_cb_data_t *cb_data);
@@ -289,30 +291,37 @@
     switch (FIX2INT(datatype)) {
     case ATTR_STRING:
         oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_VARCHAR2, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
+        oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
         break;
     case ATTR_RAW:
         oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_RAW, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
+        oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
         break;
     case ATTR_OCINUMBER:
     case ATTR_FLOAT:
     case ATTR_INTEGER:
         OCINumberSetZero(oci8_errhp, &cb_data.data.num);
+        cb_data.indp = &cb_data.ind;
         break;
     case ATTR_BINARY_DOUBLE:
         cb_data.data.dbl = 0.0;
+        cb_data.indp = &cb_data.ind;
         break;
     case ATTR_BINARY_FLOAT:
         cb_data.data.flt = 0.0;
+        cb_data.indp = &cb_data.ind;
         break;
     case ATTR_NAMED_TYPE:
         Check_Object(typeinfo, cOCI8TDO);
         tdo = DATA_PTR(typeinfo);
         oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_OBJECT, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
+        oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
         break;
     case ATTR_NAMED_COLLECTION:
         Check_Object(typeinfo, cOCI8TDO);
         tdo = DATA_PTR(typeinfo);
         oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_NAMEDCOLLECTION, tdo->hp.tdo, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
+        oci_lc(OCIObjectGetInd(oci8_envhp, oci8_errhp, cb_data.data.ptr, (dvoid**)&cb_data.indp));
         break;
     default:
         rb_raise(rb_eRuntimeError, "not supported datatype");
@@ -337,11 +346,7 @@
     sb4 size;
     sb4 idx;
     void *elem_ptr;
-    OCIInd *elem_ind_ptr;
-    OCIInd elem_ind;
 
-    elem_ind_ptr = &elem_ind;
-
     oci_lc(OCICollSize(oci8_envhp, oci8_errhp, coll, &size));
     if (RARRAY_LEN(val) < size) {
         oci_lc(OCICollTrim(oci8_envhp, oci8_errhp, size - RARRAY_LEN(val), coll));
@@ -349,10 +354,10 @@
     for (idx = 0; idx < RARRAY_LEN(val); idx++) {
         switch (FIX2INT(datatype)) {
         case ATTR_NAMED_TYPE:
-            set_attribute(self, datatype, typeinfo, cb_data->data.ptr, elem_ind_ptr, RARRAY_PTR(val)[idx]);
+            set_attribute(self, datatype, typeinfo, cb_data->data.ptr, cb_data->indp, RARRAY_PTR(val)[idx]);
             break;
         default:
-            set_attribute(self, datatype, typeinfo, (void*)&cb_data->data, elem_ind_ptr, RARRAY_PTR(val)[idx]);
+            set_attribute(self, datatype, typeinfo, (void*)&cb_data->data, cb_data->indp, RARRAY_PTR(val)[idx]);
             break;
         }
         switch (FIX2INT(datatype)) {
@@ -368,9 +373,9 @@
             break;
         }
         if (idx < size) {
-            oci_lc(OCICollAssignElem(oci8_envhp, oci8_errhp, idx, elem_ptr, elem_ind_ptr, cb_data->coll));
+            oci_lc(OCICollAssignElem(oci8_envhp, oci8_errhp, idx, elem_ptr, cb_data->indp, cb_data->coll));
         } else {
-            oci_lc(OCICollAppend(oci8_envhp, oci8_errhp, elem_ptr, elem_ind_ptr, coll));
+            oci_lc(OCICollAppend(oci8_envhp, oci8_errhp, elem_ptr, cb_data->indp, coll));
         }
     }
     return Qnil;

Modified: trunk/ruby-oci8/ext/oci8/oraconf.rb
===================================================================
--- trunk/ruby-oci8/ext/oci8/oraconf.rb	2008-07-05 14:31:24 UTC (rev 266)
+++ trunk/ruby-oci8/ext/oci8/oraconf.rb	2008-07-05 14:50:50 UTC (rev 267)
@@ -270,7 +270,7 @@
   private
 
   def self.check_ic_dir
-    print "checking for load library path... "
+    puts "checking for load library path... "
     STDOUT.flush
 
     # get library load path names
@@ -284,7 +284,7 @@
     when /mswin32|cygwin|mingw32|bccwin32/
       oci_basename = 'oci'
       oci_glob_postfix = ''
-      ocidata_basename = ['oraociei10', 'oraociicus10']
+      ocidata_basename = ['oraociei11', 'oraociicus11', 'oraociei10', 'oraociicus10']
       @@ld_envs = %w[PATH]
       so_ext = 'dll'
     when /i.86-linux/
@@ -340,24 +340,34 @@
     glob_name = "#{oci_basename}.#{so_ext}#{oci_glob_postfix}"
     ld_path = nil
     file = nil
-    @@ld_envs.collect do |env|
-      puts "(#{env})... "
-      ENV[env] && ENV[env].split(File::PATH_SEPARATOR)
-    end.flatten.each do |path|
-      next if path.nil? or path == ''
-      path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
-      files = Dir.glob(File.join(path, glob_name))
-      next if files.empty?
-      STDOUT.flush
-      next if (check_proc && !check_proc.call(files[0]))
-      file = files[0]
-      ld_path = path
+    @@ld_envs.each do |env|
+      if ENV[env].nil?
+        puts "  #{env} is not set."
+        next
+      end
+      puts "  #{env}... "
+      ENV[env].split(File::PATH_SEPARATOR).each do |path|
+        next if path.nil? or path == ''
+        print "    checking #{path}... "
+        path.gsub!(/\\/, '/') if /mswin32|cygwin|mingw32|bccwin32/ =~ RUBY_PLATFORM
+        files = Dir.glob(File.join(path, glob_name))
+        if files.empty?
+          puts "no"
+          next
+        end
+        STDOUT.flush
+        next if (check_proc && !check_proc.call(files[0]))
+        file = files[0]
+        ld_path = path
+        puts "yes"
+        break
+      end
       break
     end
 
     if ld_path.nil? and RUBY_PLATFORM =~ /linux/
       open("|/sbin/ldconfig -p") do |f|
-        print "(ld.so.conf)... "
+        print "  checking ld.so.conf... "
         STDOUT.flush
         while line = f.gets
           if line =~ /libclntsh\.so\..* => (\/.*)\/libclntsh\.so\.(.*)/
@@ -365,22 +375,22 @@
             path = $1
             next if (check_proc && !check_proc.call(file))
             ld_path = path
+            puts "yes"
             break
           end
         end
+        puts "no"
       end
     end
 
     if ld_path
       ocidata_basename.each do |basename|
         if File.exist?(File.join(ld_path, "#{basename}.#{so_ext}"))
-          puts "  found: #{file} looks like an instant client."
+          puts "  #{file} looks like an instant client."
           return ld_path
         end
       end
-      puts "  found: #{file} looks like a full client."
-    else
-      puts "  not found"
+      puts "  #{file} looks like a full client."
     end
     nil
   end
@@ -837,18 +847,20 @@
     if ic_dir =~ /^\/usr\/lib(?:64)?\/oracle\/(\d+\.\d+\.\d+\.\d+)\/client(64)?\/lib(?:64)?/
       # rpm package
       #   official x86 rpms:
-      #    library: /usr/lib/oracle/X.X.X.X.X/client/lib/
-      #    include: /usr/include/oracle/X.X.X.X.X/client/
+      #    library: /usr/lib/oracle/X.X.X.X/client/lib/
+      #    include: /usr/include/oracle/X.X.X.X/client/
       #
       #   official x86_64 rpms:
-      #    library: /usr/lib/oracle/X.X.X.X.X/client64/lib/
-      #    include: /usr/include/oracle/X.X.X.X.X/client64/
+      #    library: /usr/lib/oracle/X.X.X.X/client64/lib/
+      #    include: /usr/include/oracle/X.X.X.X/client64/
       #
-      #   third-party x86_64 rpms:
-      #    library: /usr/lib64/oracle/X.X.X.X.X/client/lib/
-      #          or /usr/lib64/oracle/X.X.X.X.X/client/lib64/
-      #    include: /usr/include/oracle/X.X.X.X.X/client/
+      #   third-party x86_64 rpms(*1):
+      #    library: /usr/lib64/oracle/X.X.X.X/client/lib/
+      #          or /usr/lib64/oracle/X.X.X.X/client/lib64/
+      #    include: /usr/include/oracle/X.X.X.X/client/
       #
+      #   *1 These had been used before Oracle released official x86_64 rpms.
+      #
       lib_dir = ic_dir
       inc_dir = "/usr/include/oracle/#{$1}/client#{$2}"
     else
@@ -932,21 +944,82 @@
       return
     end
 
-    if RUBY_PLATFORM =~ /i.*-darwin/
+    if RUBY_PLATFORM =~ /darwin/
+      is_intelmac = ([1].pack('s') == "\001\000")
+      arch_ppc_error = false
+      arch_i386_error = false
       open('mkmf.log', 'r') do |f|
         while line = f.gets
+          # universal-darwin8.0 (Mac OS X 10.4?)
           if line.include? 'cputype (18, architecture ppc) does not match cputype (7)'
+            # try to link an i386 library but the instant client is ppc.
+            arch_i386_error = true
+          end
+          if line.include? 'cputype (7, architecture i386) does not match cputype (18)'
+            # try to link a ppc library but the instant client is i386.
+            arch_ppc_error = true
+          end
+          if line.include? '/libclntsh.dylib load command 8 unknown cmd field'
             raise <<EOS
-Oracle doesn't support intel mac.
-  http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/223854
+Intel mac instant client is for Mac OS X 10.5.
+It doesn't work on Mac OS X 10.4 or before.
 
-There are three solutions:
-1. Compile ruby as ppc binary.
-2. Wait until Oracle releases mac intel binary.
-3. Use a third-party ODBC driver and ruby-odbc instead.
-     http://www.actualtechnologies.com/
+You have three workarounds.
+  1. Compile ruby as ppc binary and use it with ppc instant client.
+  2. Use JRuby and JDBC
+  3. Use a third-party ODBC driver and ruby-odbc.
 EOS
+            # '
           end
+          # universal-darwin9.0 (Mac OS X 10.5?)
+          if line.include? 'Undefined symbols for architecture i386:'
+            # try to link an i386 library but the instant client is ppc.
+            arch_i386_error = true
+          end
+          if line.include? 'Undefined symbols for architecture ppc:'
+            # try to link a ppc library but the instant client is i386.
+            arch_ppc_error = true
+          end
+
+          if arch_i386_error
+            if is_intelmac
+              # intel mac and '-arch i386' error
+              raise <<EOS
+Could not compile with Oracle instant client.
+Use intel mac instant client.
+EOS
+            else
+              # ppc mac and '-arch i386' error
+              raise <<EOS
+Could not compile with Oracle instant client.
+You may need to set a environment variable:
+    RC_ARCHS=ppc
+    export RC_ARCHS
+If it does not fix the problem, delete all '-arch i386'
+in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
+EOS
+            end
+          end
+
+          if arch_ppc_error
+            if is_intelmac
+              # intel mac and '-arch ppc' error
+              raise <<EOS
+Could not compile with Oracle instant client.
+You may need to set a environment variable:
+    RC_ARCHS=i386
+    export RC_ARCHS
+If it does not fix the problem, delete all '-arch ppc'
+in '#{Config::CONFIG['archdir']}/rbconfig.rb'.
+EOS
+            else
+              # ppc mac and '-arch ppc' error
+              raise <<EOS
+Could not compile with Oracle instant client.
+Use ppc instant client.
+EOS
+            end
+          end
         end
       end
     end

Modified: trunk/ruby-oci8/lib/oci8/object.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/object.rb	2008-07-05 14:31:24 UTC (rev 266)
+++ trunk/ruby-oci8/lib/oci8/object.rb	2008-07-05 14:50:50 UTC (rev 267)
@@ -519,6 +519,18 @@
 
 class OCI8
   module BindType
+
+    class NamedType
+      def self.create(con, val, param, max_array_size)
+        case param
+        when Hash
+          self.new(con, val, param[:length], max_array_size)
+        else
+          self.new(con, val, param, max_array_size)
+        end
+      end
+    end
+
     class Object < OCI8::BindType::NamedType
       alias :get_orig get
       def set(val)

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2008-07-05 14:31:24 UTC (rev 266)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2008-07-05 14:50:50 UTC (rev 267)
@@ -483,6 +483,9 @@
           else
             key = val.class
           end
+        elsif key.class == Class && key < OCI8::Object::Base
+          param = @con.get_tdo_by_class(key)
+          key = :named_type
         end
       when OCI8::Metadata::Base
         key = param.data_type




More information about the ruby-oci8-commit mailing list