[ruby-oci8-commit] [295] branches/ruby-oci8-1.0: * lib/oci8.rb.in:

nobody at rubyforge.org nobody at rubyforge.org
Sun Dec 14 03:03:02 EST 2008


Revision: 295
Author:   kubo
Date:     2008-12-14 03:03:02 -0500 (Sun, 14 Dec 2008)

Log Message:
-----------
* lib/oci8.rb.in:
    1. fix to fetch a rowid column as s String.
    2. change the return type of OCI8#rowid from OCIRowid
       to String. It is a local call on Oracle 9.0 or upper.
       But on Oracle 8.x client, it needs one network roundtrip
       to convert OCIRowid to String on server side.
    3. fix OCI8#describe_table to prevent OCIStillExecuting when
       non-blocking mode is enabled and it needs a time to
       retrieve table information.
* ext/oci8/extconf.rb, ext/oci8/oci8.c: add OCIRowid#to_s
    when OCIRowidToChar() is available.
* test/test_all.rb, test/test_rowid.rb: add a rowid test case.
* test/test_dbi_clob.rb: fix to pass tests when the test directory
    path is too long.

Modified Paths:
--------------
    branches/ruby-oci8-1.0/ChangeLog
    branches/ruby-oci8-1.0/ext/oci8/extconf.rb
    branches/ruby-oci8-1.0/ext/oci8/oci8.c
    branches/ruby-oci8-1.0/lib/oci8.rb.in
    branches/ruby-oci8-1.0/test/test_all.rb
    branches/ruby-oci8-1.0/test/test_dbi_clob.rb

Added Paths:
-----------
    branches/ruby-oci8-1.0/test/test_rowid.rb

Modified: branches/ruby-oci8-1.0/ChangeLog
===================================================================
--- branches/ruby-oci8-1.0/ChangeLog	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/ChangeLog	2008-12-14 08:03:02 UTC (rev 295)
@@ -1,3 +1,19 @@
+2008-12-14  KUBO Takehiro  <kubo at jiubao.org>
+	* lib/oci8.rb.in:
+	    1. fix to fetch a rowid column as s String.
+	    2. change the return type of OCI8#rowid from OCIRowid
+	       to String. It is a local call on Oracle 9.0 or upper.
+	       But on Oracle 8.x client, it needs one network roundtrip
+	       to convert OCIRowid to String on server side.
+	    3. fix OCI8#describe_table to prevent OCIStillExecuting when
+	       non-blocking mode is enabled and it needs a time to
+	       retrieve table information.
+	* ext/oci8/extconf.rb, ext/oci8/oci8.c: add OCIRowid#to_s
+	    when OCIRowidToChar() is available.
+	* test/test_all.rb, test/test_rowid.rb: add a rowid test case.
+	* test/test_dbi_clob.rb: fix to pass tests when the test directory
+	    path is too long.
+
 2008-08-10  KUBO Takehiro  <kubo at jiubao.org>
 	* NEWS: add changes between 1.0.2 and 1.0.3.
 	* VERSION: change version to 1.0.3.
@@ -12,7 +28,7 @@
 2008-08-09  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/lob.c: fix OCILobLocator#getLength for a lob over 1GB,
 	    which affect OCI8::LOB#size and OCI8::LOB#read. fix
-	    OCILobLocator#read and OCILobLocator#write to set offset over 2BG,
+	    OCILobLocator#read and OCILobLocator#write to set offset over 2GB,
 	    which affect OCI8::LOB#read and OCI8::LOB#write.
 	    (This probmem was reported by Jonathan Hadders.)
 

Modified: branches/ruby-oci8-1.0/ext/oci8/extconf.rb
===================================================================
--- branches/ruby-oci8-1.0/ext/oci8/extconf.rb	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/ext/oci8/extconf.rb	2008-12-14 08:03:02 UTC (rev 295)
@@ -77,6 +77,8 @@
 have_func("OCILobGetChunkSize")
 have_func("OCILobLocatorAssign")
 
+have_func("OCIRowidToChar")
+
 $defs.push("-DHAVE_OCIRESET") unless /80./ =~ oraconf.version
 
 # Checking gcc or not

Modified: branches/ruby-oci8-1.0/ext/oci8/oci8.c
===================================================================
--- branches/ruby-oci8-1.0/ext/oci8/oci8.c	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/ext/oci8/oci8.c	2008-12-14 08:03:02 UTC (rev 295)
@@ -77,6 +77,8 @@
 VALUE cOraDate;
 VALUE cOraNumber;
 
+static void Init_OCIRowid(void);
+
 void
 Init_oci8lib()
 {
@@ -131,7 +133,46 @@
   Init_ora_date();
   Init_ora_number();
 
+  Init_OCIRowid();
+
 #ifdef DEBUG_CORE_FILE
   signal(SIGSEGV, SIG_DFL);
 #endif
 }
+
+#if defined(WIN32)
+typedef sword (*OCIRowidToChar_func_t)(OCIRowid *rowidDesc, OraText *outbfp, ub2 *outbflp, OCIError *errhp);
+static OCIRowidToChar_func_t OCIRowidToChar_func;
+#define OCIRowidToChar OCIRowidToChar_func
+#endif
+
+#if defined(WIN32) || defined(HAVE_OCIROWIDTOCHAR)
+static VALUE oci8_rowid_to_s(VALUE self)
+{
+  oci8_handle_t *h;
+  char buf[64];
+  ub2 buflen = sizeof(buf);
+  sword rv;
+
+  Get_Handle(self, h);
+  rv = OCIRowidToChar(h->hp, (text*)buf, &buflen, h->errhp);
+  if (rv != OCI_SUCCESS)
+    oci8_raise(h->errhp, rv, NULL);
+  return rb_str_new(buf, buflen);
+}
+#endif
+
+static void Init_OCIRowid(void)
+{
+#if defined(WIN32)
+  HANDLE hModule = GetModuleHandle("OCI.DLL");
+  if (hModule != NULL) {
+    OCIRowidToChar_func = (OCIRowidToChar_func_t)GetProcAddress(hModule, "OCIRowidToChar");
+  }
+  if (OCIRowidToChar_func != NULL) {
+    rb_define_method(cOCIRowid, "to_s", oci8_rowid_to_s, 0);
+  }
+#elif defined(HAVE_OCIROWIDTOCHAR)
+  rb_define_method(cOCIRowid, "to_s", oci8_rowid_to_s, 0);
+#endif
+}

Modified: branches/ruby-oci8-1.0/lib/oci8.rb.in
===================================================================
--- branches/ruby-oci8-1.0/lib/oci8.rb.in	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/lib/oci8.rb.in	2008-12-14 08:03:02 UTC (rev 295)
@@ -351,7 +351,7 @@
   def describe_table(table_name)
     desc = @@env.alloc(OCIDescribe)
     desc.attrSet(OCI_ATTR_DESC_PUBLIC, -1)
-    desc.describeAny(@svc, table_name.to_s, OCI_PTYPE_UNK)
+    do_ocicall(@ctx) { desc.describeAny(@svc, table_name.to_s, OCI_PTYPE_UNK) }
     param = desc.attrGet(OCI_ATTR_PARAM)
 
     case param.attrGet(OCI_ATTR_PTYPE)
@@ -811,8 +811,25 @@
       @stmttype = nil
     end # close
 
+    # Get the rowid of the last inserted/updated/deleted row.
     def rowid
-      @stmt.attrGet(OCI_ATTR_ROWID)
+      # get the binary rowid
+      rid = @stmt.attrGet(OCI_ATTR_ROWID)
+      # convert it to a string rowid.
+      if rid.respond_to? :to_s
+        # (Oracle 9.0 or upper)
+        rid.to_s
+      else
+        # (Oracle 8.1 or lower)
+        stmt = @env.alloc(OCIStmt)
+        stmt.prepare('begin :1 := :2; end;')
+        b = stmt.bindByPos(1, OCI8::SQLT_CHR, 64)
+        stmt.bindByPos(2, OCI8::SQLT_RDD, rid)
+        do_ocicall(@ctx) { stmt.execute(@svc, 1, OCI_DEFAULT) }
+        str_rid = b.get()
+        stmt.free()
+        str_rid
+      end
     end
 
     def prefetch_rows=(rows)
@@ -899,6 +916,8 @@
         datatype = :nclob if p.attrGet(OCI_ATTR_CHARSET_FORM) == SQLCS_NCHAR
       when SQLT_BIN
         datasize *= 2 if OCI8::BindType::Mapping[datatype] == OCI8::BindType::String
+      when SQLT_RDD
+        datasize = 64
       end
 
       bind_or_define(:define, i, nil, datatype, datasize, precision, scale, true)
@@ -1210,7 +1229,7 @@
   # datatype        type     size prec scale
   # -------------------------------------------------
   # ROWID         SQLT_RDD      4    0    0
-  BindType::Mapping[OCI8::SQLT_RDD] = BindType::OCIRowid
+  BindType::Mapping[OCI8::SQLT_RDD] = BindType::String
 
   # datatype           type     size prec scale
   # -----------------------------------------------------

Modified: branches/ruby-oci8-1.0/test/test_all.rb
===================================================================
--- branches/ruby-oci8-1.0/test/test_all.rb	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/test/test_all.rb	2008-12-14 08:03:02 UTC (rev 295)
@@ -18,6 +18,7 @@
 require "#{srcdir}/test_oci8"
 require "#{srcdir}/test_connstr"
 require "#{srcdir}/test_metadata"
+require "#{srcdir}/test_rowid"
 
 # Ruby/DBI
 begin

Modified: branches/ruby-oci8-1.0/test/test_dbi_clob.rb
===================================================================
--- branches/ruby-oci8-1.0/test/test_dbi_clob.rb	2008-12-13 15:04:19 UTC (rev 294)
+++ branches/ruby-oci8-1.0/test/test_dbi_clob.rb	2008-12-14 08:03:02 UTC (rev 295)
@@ -11,13 +11,14 @@
   end
 
   def test_insert
-    @dbh.do("DELETE FROM test_clob WHERE filename = :1", $lobfile)
+    filename = File.basename($lobfile)
+    @dbh.do("DELETE FROM test_clob WHERE filename = :1", filename)
 
     # insert an empty clob and get the rowid.
-    rowid = @dbh.execute("INSERT INTO test_clob(filename, content) VALUES (:1, EMPTY_CLOB())", $lobfile) do |sth|
+    rowid = @dbh.execute("INSERT INTO test_clob(filename, content) VALUES (:1, EMPTY_CLOB())", filename) do |sth|
       sth.func(:rowid)
     end
-    lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", $lobfile)[0]
+    lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", filename)[0]
     begin
       open($lobfile) do |f|
         while f.gets()
@@ -30,8 +31,9 @@
   end
 
   def test_read
+    filename = File.basename($lobfile)
     test_insert() # first insert data.
-    lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", $lobfile)[0]
+    lob = @dbh.select_one("SELECT content FROM test_clob WHERE filename = :1 FOR UPDATE", filename)[0]
     begin
       open($lobfile) do |f|
         while buf = lob.read($lobreadnum)

Added: branches/ruby-oci8-1.0/test/test_rowid.rb
===================================================================
--- branches/ruby-oci8-1.0/test/test_rowid.rb	                        (rev 0)
+++ branches/ruby-oci8-1.0/test/test_rowid.rb	2008-12-14 08:03:02 UTC (rev 295)
@@ -0,0 +1,38 @@
+require 'oci8'
+require 'runit/testcase'
+require 'runit/cui/testrunner'
+require File.dirname(__FILE__) + '/config'
+
+class TestRowid < RUNIT::TestCase
+
+  def setup
+    @conn = get_oci_connection()
+  end
+
+  def teardown
+    @conn.logoff
+  end
+
+  def test_rowid
+    drop_table('test_table')
+    sql = <<-EOS
+CREATE TABLE test_table (N NUMBER(38))
+EOS
+    @conn.exec(sql)
+    cursor = @conn.parse("INSERT INTO test_table values(1)");
+    cursor.exec
+    rid1 = cursor.rowid
+    assert_instance_of(String, rid1)
+    cursor.close
+    rid2 = nil
+    @conn.exec('select rowid from test_table where rowid = :1', rid1) do |row|
+      rid2 = row[0]
+    end
+    assert_equal(rid2, rid1)
+    drop_table('test_table')
+  end
+end # TestRowid
+
+if $0 == __FILE__
+  RUNIT::CUI::TestRunner.run(TestRowid.suite())
+end




More information about the ruby-oci8-commit mailing list