[ruby-oci8-commit] [287] trunk/ruby-oci8: * ext/oci8/bind.c, ext/oci8/stmt.c: disable DYNAMIC_FETCH to fetch

nobody at rubyforge.org nobody at rubyforge.org
Sun Aug 31 10:11:40 EDT 2008


Revision: 287
Author:   kubo
Date:     2008-08-31 10:11:39 -0400 (Sun, 31 Aug 2008)

Log Message:
-----------
* ext/oci8/bind.c, ext/oci8/stmt.c: disable DYNAMIC_FETCH to fetch
    LONG or LONG RAW columns. It doesn't work well.
* lib/oci8/metadata.rb: define char_size for Oracle 8i.
* lib/oci8/oci8.rb: define OCI8::BindType::Long and
    OCI8::BindType::LongRaw as subclasses of OCI8::BindType::String
    and OCI8::BindType::RAW respectively. fix
    OCI8::BindType::String.create and OCI8::BindType::RAW.create
    for strings longer than 4000.
* test/test_array_dml.rb: add workaround of "ORA-01036: illegal
    variable name/number" by renaming a bind variable name ":N"
    to ":1". I guess this is a problem in the Oracle library.
* test/test_break.rb, test/test_dbi.rb, test/test_metadata.rb:
    fix test codes for Oracle 8i or lower.
* test/test_oci8.rb: revise a test for LONG columns.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/bind.c
    trunk/ruby-oci8/ext/oci8/stmt.c
    trunk/ruby-oci8/lib/oci8/metadata.rb
    trunk/ruby-oci8/lib/oci8/oci8.rb
    trunk/ruby-oci8/test/test_array_dml.rb
    trunk/ruby-oci8/test/test_break.rb
    trunk/ruby-oci8/test/test_dbi.rb
    trunk/ruby-oci8/test/test_metadata.rb
    trunk/ruby-oci8/test/test_oci8.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/ChangeLog	2008-08-31 14:11:39 UTC (rev 287)
@@ -1,3 +1,19 @@
+2008-08-31  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/bind.c, ext/oci8/stmt.c: disable DYNAMIC_FETCH to fetch
+	    LONG or LONG RAW columns. It doesn't work well.
+	* lib/oci8/metadata.rb: define char_size for Oracle 8i.
+	* lib/oci8/oci8.rb: define OCI8::BindType::Long and
+	    OCI8::BindType::LongRaw as subclasses of OCI8::BindType::String
+	    and OCI8::BindType::RAW respectively. fix
+	    OCI8::BindType::String.create and OCI8::BindType::RAW.create
+	    for strings longer than 4000.
+	* test/test_array_dml.rb: add workaround of "ORA-01036: illegal
+	    variable name/number" by renaming a bind variable name ":N"
+	    to ":1". I guess this is a problem in the Oracle library.
+	* test/test_break.rb, test/test_dbi.rb, test/test_metadata.rb:
+	    fix test codes for Oracle 8i or lower.
+	* test/test_oci8.rb: revise a test for LONG columns.
+
 2008-08-28  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/apiwrap.yml: OCINumberSign is unavailable on Oracle 8.
 	* lib/DBD/OCI8/OCI8.rb: A data dictionary all_constraints doesn't have

Modified: trunk/ruby-oci8/ext/oci8/bind.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/bind.c	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/ext/oci8/bind.c	2008-08-31 14:11:39 UTC (rev 287)
@@ -90,6 +90,7 @@
     SQLT_LVB
 };
 
+#ifdef USE_DYNAMIC_FETCH /* don't use DYNAMIC_FETCH. It doesn't work well... */
 /*
  * bind_long
  */
@@ -173,13 +174,21 @@
 {
     bind_long_t *bl = (bind_long_t *)((char*)obind->valuep + obind->alloc_sz * idx);
 
-    if (piece == OCI_FIRST_PIECE) {
+    switch (piece) {
+    case OCI_NEXT_PIECE:
+    case OCI_LAST_PIECE:
+        if (bl->alen > 0) {
+            if (!RTEST(bl->obj)) {
+                bl->obj = rb_str_buf_new(bl->alen);
+            }
+            rb_str_buf_cat(bl->obj, bl->buf, bl->alen);
+        }
+        break;
+    default:
+        /* OCI_FIRST_PIECE is passed at the first call according to manuals.
+         * But OCI_ONE_PIECE is passed on Oracle 8 and 8i on Windows...
+         */
         bl->obj = Qnil;
-    } else if (bl->alen > 0) {
-        if (!RTEST(bl->obj)) {
-            bl->obj = rb_str_buf_new(bl->alen);
-        }
-        rb_str_buf_cat(bl->obj, bl->buf, bl->alen);
     }
     *valuepp = bl->buf;
     *alenpp = &bl->alen;
@@ -222,6 +231,7 @@
     NULL,
     SQLT_BIN
 };
+#endif /* USE_DYNAMIC_FETCH */
 
 /*
  * bind_fixnum
@@ -467,8 +477,10 @@
     /* register primitive data types. */
     oci8_define_bind_class("String", &bind_string_class);
     oci8_define_bind_class("RAW", &bind_raw_class);
+#ifdef USE_DYNAMIC_FETCH
     oci8_define_bind_class("Long", &bind_long_class);
     oci8_define_bind_class("LongRaw", &bind_long_raw_class);
+#endif /* USE_DYNAMIC_FETCH */
     oci8_define_bind_class("Fixnum", &bind_fixnum_class);
     oci8_define_bind_class("Float", &bind_float_class);
     if (oracle_client_version >= ORAVER_10_1) {

Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/ext/oci8/stmt.c	2008-08-31 14:11:39 UTC (rev 287)
@@ -255,6 +255,7 @@
         mode = svcctx->is_autocommit ? OCI_COMMIT_ON_SUCCESS : OCI_DEFAULT;
     }
     rv = oci8_call_stmt_execute(svcctx, stmt, iters, mode);
+#ifdef USE_DYNAMIC_FETCH
     while (rv == OCI_NEED_DATA) {
         oci8_bind_t *obind;
         const oci8_bind_class_t *bind_class;
@@ -301,6 +302,7 @@
         }
         rv = oci8_call_stmt_execute(svcctx, stmt, iters, mode);
     }
+#endif /* USE_DYNAMIC_FETCH */
     if (IS_OCI_ERROR(rv)) {
         oci8_raise(oci8_errhp, rv, stmt->base.hp.stmt);
     }
@@ -352,6 +354,7 @@
         obind = (oci8_bind_t *)obind->base.next;
     } while (obind != (oci8_bind_t*)stmt->base.children);
     rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
+#ifdef USE_DYNAMIC_FETCH
     while (rv == OCI_NEED_DATA) {
         /* get piece info. */
         dvoid *hp;
@@ -376,7 +379,7 @@
                 case OCI_PARAM_OUT:
                     if (bind_class->out == NULL)
                         rb_bug("....");
-                    bind_class->out(obind, idx, piece == OCI_FIRST_PIECE, &valuep, &alenp, &indp);
+                    bind_class->out(obind, idx, piece, &valuep, &alenp, &indp);
                     break;
                 default:
                     rb_bug("ruby-oci8: expect OCI_PARAM_OUT but %d", in_out);
@@ -391,34 +394,38 @@
         }
         rv = OCIStmtFetch_nb(svcctx, stmt->base.hp.stmt, oci8_errhp, 1, OCI_FETCH_NEXT, OCI_DEFAULT);
     }
+#endif /* USE_DYNAMIC_FETCH */
     if (rv == OCI_NO_DATA) {
         return Qnil;
     }
     if (IS_OCI_ERROR(rv)) {
         oci8_raise(oci8_errhp, rv, stmt->base.hp.stmt);
     }
+#ifdef USE_DYNAMIC_FETCH
     obind = (oci8_bind_t *)stmt->base.children;
     do {
         /* set piece info. */
         void *valuep;
         ub4 *alenp;
         void *indp;
+        ub1 piece = OCI_LAST_PIECE;
 
         if (obind->base.type == OCI_HTYPE_DEFINE) {
             bind_class = (const oci8_bind_class_t *)obind->base.klass;
             if (bind_class->out != NULL) {
                 if (obind->maxar_sz == 0) {
-                    bind_class->out(obind, 0, 0, &valuep, &alenp, &indp);
+                    bind_class->out(obind, 0, piece, &valuep, &alenp, &indp);
                 } else {
                     ub4 idx;
                     for (idx = 0; idx < obind->curar_sz; idx++) {
-                        bind_class->out(obind, idx, 0, &valuep, &alenp, &indp);
+                        bind_class->out(obind, idx, piece, &valuep, &alenp, &indp);
                     }
                 }
             }
         }
         obind = (oci8_bind_t *)obind->base.next;
     } while (obind != (oci8_bind_t*)stmt->base.children);
+#endif /* USE_DYNAMIC_FETCH */
     ary = rb_ary_new2(RARRAY_LEN(stmt->defns));
     for (idx = 0; idx < RARRAY_LEN(stmt->defns); idx++) {
         rb_ary_store(ary, idx, rb_funcall(RARRAY_PTR(stmt->defns)[idx], oci8_id_get, 0));

Modified: trunk/ruby-oci8/lib/oci8/metadata.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/metadata.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/lib/oci8/metadata.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -1345,8 +1345,6 @@
         # returns the column character length which is the number of
         # characters allowed in the column. It is the counterpart of
         # OCI8::Metadata::Column#data_size which gets the byte length.
-        #
-        # (unavailable on Oracle 8.1 or lower)
         def char_size
           __ub2(OCI_ATTR_CHAR_SIZE)
         end
@@ -1354,11 +1352,17 @@
         def char_used?
           false
         end
+
+        def char_size
+          data_size
+        end
       end
 
       # The maximum size of the column. This length is
-      # returned in bytes and not characters for strings and raws. It
-      # returns 22 for NUMBERs.
+      # returned in bytes and not characters for strings and raws.
+      # This returns character length multiplied by NLS ratio for
+      # character-length semantics columns when using Oracle 9i
+      # or upper.
       def data_size
         __ub2_nc(OCI_ATTR_DATA_SIZE)
       end

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -196,7 +196,13 @@
       def self.create(con, val, param, max_array_size)
         case param
         when Hash
-          length = param[:length] || 4000
+          # 1333 = ceil(4000 (max size of char) / 3 (NLS ratio of UTF8))
+          length = 1333 # default length
+          if param[:length]
+            length = param[:length]
+          elsif val.respond_to? :to_str and val.to_str.size > length
+            length = val.to_str.size
+          end
         when OCI8::Metadata::Base
           case param.data_type
           when :char, :varchar2
@@ -220,7 +226,12 @@
       def self.create(con, val, param, max_array_size)
         case param
         when Hash
-          length = param[:length] || 4000
+          length = 400 # default length
+          if param[:length]
+            length = param[:length]
+          elsif val.respond_to? :to_str and val.to_str.size > length
+            length = val.to_str.size
+          end
         when OCI8::Metadata::Base
           length = param.data_size
         end
@@ -228,13 +239,13 @@
       end
     end
 
-    class Long
+    class Long < OCI8::BindType::String
       def self.create(con, val, param, max_array_size)
         self.new(con, val, con.long_read_len, max_array_size)
       end
     end
 
-    class LongRaw
+    class LongRaw < OCI8::BindType::RAW
       def self.create(con, val, param, max_array_size)
         self.new(con, val, con.long_read_len, max_array_size)
       end

Modified: trunk/ruby-oci8/test/test_array_dml.rb
===================================================================
--- trunk/ruby-oci8/test/test_array_dml.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/test/test_array_dml.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -227,7 +227,7 @@
     cursor.exec_array
     cursor.close
 
-    cursor = @conn.parse("DELETE FROM test_table WHERE N=:N")
+    cursor = @conn.parse("DELETE FROM test_table WHERE N=:1")
     cursor.max_array_size = max_array_size
     delete_arr = Array.new
     1.upto(max_array_size) do |i|
@@ -280,7 +280,7 @@
     cursor.exec_array
     cursor.close
 
-    cursor = @conn.parse("UPDATE test_table SET V=:V WHERE N=:N")
+    cursor = @conn.parse("UPDATE test_table SET V=:1 WHERE N=:2")
     cursor.max_array_size = max_array_size
     update_arr = Array.new
     update_v_arr = Array.new

Modified: trunk/ruby-oci8/test/test_break.rb
===================================================================
--- trunk/ruby-oci8/test/test_break.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/test/test_break.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -55,15 +55,26 @@
   end
 
   def test_non_blocking_mode
+    is_windows_server = false
+    @conn.exec('select banner from v$version') do |row|
+      is_windows_server = true if row[0].include? 'Windows'
+    end
+
     @conn.non_blocking = true
     assert_equal(true, @conn.non_blocking?)
     expect = []
-    expect[PLSQL_DONE] = "Invalid status"
-    if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
-      # raise after sleeping #{TIME_IN_PLSQL} seconds.
-      expect[OCIBREAK] = TIME_IN_PLSQL
+    if is_windows_server
+      if $oracle_server_version >= OCI8::ORAVER_9_1
+        # raise after sleeping #{TIME_IN_PLSQL} seconds.
+        expect[PLSQL_DONE] = "Invalid status"
+        expect[OCIBREAK] = TIME_IN_PLSQL
+      else
+        expect[PLSQL_DONE] = TIME_IN_PLSQL
+        expect[OCIBREAK] = "Invalid status"
+      end
     else
       # raise immediately by OCI8#break.
+      expect[PLSQL_DONE] = "Invalid status"
       expect[OCIBREAK] = TIME_TO_BREAK
     end
     expect[SEND_BREAK]   = TIME_TO_BREAK

Modified: trunk/ruby-oci8/test/test_dbi.rb
===================================================================
--- trunk/ruby-oci8/test/test_dbi.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/test/test_dbi.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -102,13 +102,28 @@
     sth = @dbh.prepare("INSERT INTO test_table VALUES (:C, :V, :N, :D1, :D2, :D3, :D4, :INT, :BIGNUM)")
     1.upto(10) do |i|
       if i == 1
-	dt = nil
-        v = ''
+        if OCI8::oracle_client_version >= OCI8::ORAVER_9_1
+          dt = nil
+          v = ''
+          sth.execute(format("%10d", i * 10), v, i, dt, dt, dt, dt, i, i)
+        else
+          # explicitly bind nil with datatype to avoid ORA-01475 when using Oracle 8i.
+          sth.bind_param(1, format("%10d", i * 10))
+          sth.bind_param(2, '')
+          sth.bind_param(3, i)
+          sth.bind_param(4, nil, {'type' => OraDate})
+          sth.bind_param(5, nil, {'type' => OraDate})
+          sth.bind_param(6, nil, {'type' => OraDate})
+          sth.bind_param(7, nil, {'type' => OraDate})
+          sth.bind_param(8, i)
+          sth.bind_param(9, i)
+          sth.execute
+        end
       else
-	dt = OraDate.new(2000 + i, 8, 3, 23, 59, 59)
+        dt = OraDate.new(2000 + i, 8, 3, 23, 59, 59)
         v = i.to_s
+        sth.execute(format("%10d", i * 10), v, i, dt, dt, dt, dt, i, i)
       end
-      sth.execute(format("%10d", i * 10), v, i, dt, dt, dt, dt, i, i)
     end
     sth.finish
     sth = @dbh.prepare("SELECT * FROM test_table ORDER BY c")
@@ -165,47 +180,62 @@
   end
 
   def test_column_info
+    if $oracle_version < OCI8::ORAVER_8_1
+      begin
+        @dbh.columns('tab')
+      rescue RuntimeError
+        assert_equal("This feature is unavailable on Oracle 8.0", $!.to_s)
+      end
+      return
+    end
+
     # data_size factor for nchar charset_form.
-    sth = @dbh.execute("select CAST('1' AS NCHAR(1)) from dual")
+    sth = @dbh.execute("select N'1' from dual")
     cfrm = sth.column_info[0]['precision']
     if $oracle_version >=  OCI8::ORAVER_9_1
       # data_size factor for char semantics.
       sth = @dbh.execute("select CAST('1' AS CHAR(1 char)) from dual")
       csem = sth.column_info[0]['precision']
+    else
+      csem = 1
     end
 
+    ora80 = OCI8::ORAVER_8_0
+    ora81 = OCI8::ORAVER_8_1
+    ora91 = OCI8::ORAVER_9_1
+    ora101 = OCI8::ORAVER_10_1
     coldef =
       [
        # oracle_version, definition,    sql_type,        type_name, nullable, precision,scale,indexed,primary,unique,default
-       [800, "CHAR(10) NOT NULL",        DBI::SQL_CHAR,    'CHAR',     false,        10, nil, true, true, true, nil],
-       [900, "CHAR(10 CHAR)",            DBI::SQL_CHAR,    'CHAR',     true,  10 * csem, nil, false,false,false,nil],
-       [800, "NCHAR(10)",                DBI::SQL_CHAR,    'NCHAR',    true,  10 * cfrm, nil, true, false,true, nil],
-       [800, "VARCHAR2(10) DEFAULT 'a''b'", DBI::SQL_VARCHAR, 'VARCHAR2', true,         10, nil, true, false,false, "a'b"],
-       [900, "VARCHAR2(10 CHAR)",        DBI::SQL_VARCHAR, 'VARCHAR2', true,  10 * csem, nil, false,false,false,nil],
-       [800, "NVARCHAR2(10)",            DBI::SQL_VARCHAR, 'NVARCHAR2',true,  10 * cfrm, nil, false,false,false,nil],
-       [800, "RAW(10)",                  DBI::SQL_VARBINARY, 'RAW',    true,         10, nil, false,false,false,nil],
-       [800, "CLOB",                     DBI::SQL_CLOB,    'CLOB',     true,       4000, nil, false,false,false,nil],
-       [800, "NCLOB",                    DBI::SQL_CLOB,    'NCLOB',    true,       4000, nil, false,false,false,nil],
-       [800, "BLOB",                     DBI::SQL_BLOB,    'BLOB',     true,       4000, nil, false,false,false,nil],
-       [800, "BFILE",                    DBI::SQL_BLOB,    'BFILE',    true,       4000, nil, false,false,false,nil],
-       [800, "NUMBER",                   DBI::SQL_NUMERIC, 'NUMBER',   true,         38, nil, false,false,false,nil],
-       [800, "NUMBER(10)",               DBI::SQL_NUMERIC, 'NUMBER',   true,         10,   0, false,false,false,nil],
-       [800, "NUMBER(10,2)",             DBI::SQL_NUMERIC, 'NUMBER',   true,         10,   2, false,false,false,nil],
-       [800, "FLOAT",                    DBI::SQL_FLOAT,   'FLOAT',    true, (126 * 0.30103).ceil, nil, false,false,false,nil],
-       [800, "FLOAT(10)",                DBI::SQL_FLOAT,   'FLOAT',    true, (10 * 0.30103).ceil, nil, false,false,false,nil],
-       [1000,"BINARY_FLOAT",             DBI::SQL_FLOAT,   'BINARY_FLOAT', true,      7, nil, false,false,false,nil],
-       [1000,"BINARY_DOUBLE",            DBI::SQL_DOUBLE,  'BINARY_DOUBLE', true,    16, nil, false,false,false,nil],
-       [800, "DATE",                     DBI::SQL_DATE,    'DATE',     true,         19, nil, false,false,false,nil],
-       [900, "TIMESTAMP",                DBI::SQL_TIMESTAMP, 'TIMESTAMP', true,  20 + 6, nil, false,false,false,nil],
-       [900, "TIMESTAMP(9)",             DBI::SQL_TIMESTAMP, 'TIMESTAMP', true,  20 + 9, nil, false,false,false,nil],
-       [900, "TIMESTAMP WITH TIME ZONE",          DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH TIME ZONE', true,  27 + 6, nil, false,false,false,nil],
-       [900, "TIMESTAMP(9) WITH TIME ZONE",       DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH TIME ZONE', true,  27 + 9, nil, false,false,false,nil],
-       [900, "TIMESTAMP WITH LOCAL TIME ZONE",    DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH LOCAL TIME ZONE', true,  20 + 6, nil, false,false,false,nil],
-       [900, "TIMESTAMP(9) WITH LOCAL TIME ZONE", DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH LOCAL TIME ZONE', true,  20 + 9, nil, false,false,false,nil],
-       [900, "INTERVAL YEAR TO MONTH",      DBI::SQL_OTHER, 'INTERVAL YEAR TO MONTH', true, 2 + 3, nil, false,false,false,nil],
-       [900, "INTERVAL YEAR(4) TO MONTH",   DBI::SQL_OTHER, 'INTERVAL YEAR TO MONTH', true, 4 + 3, nil, false,false,false,nil],
-       [900, "INTERVAL DAY TO SECOND",      DBI::SQL_OTHER, 'INTERVAL DAY TO SECOND', true, 2 + 10 + 6, nil, false,false,false,nil],
-       [900, "INTERVAL DAY(4) TO SECOND(9)",DBI::SQL_OTHER, 'INTERVAL DAY TO SECOND', true, 4 + 10 + 9, nil, false,false,false,nil],
+       [ora80, "CHAR(10) NOT NULL",        DBI::SQL_CHAR,    'CHAR',     false,        10, nil, true, true, true, nil],
+       [ora91, "CHAR(10 CHAR)",            DBI::SQL_CHAR,    'CHAR',     true,  10 * csem, nil, false,false,false,nil],
+       [ora80, "NCHAR(10)",                DBI::SQL_CHAR,    'NCHAR',    true,  10 * cfrm, nil, true, false,true, nil],
+       [ora80, "VARCHAR2(10) DEFAULT 'a''b'", DBI::SQL_VARCHAR, 'VARCHAR2', true,         10, nil, true, false,false, "a'b"],
+       [ora91, "VARCHAR2(10 CHAR)",        DBI::SQL_VARCHAR, 'VARCHAR2', true,  10 * csem, nil, false,false,false,nil],
+       [ora80, "NVARCHAR2(10)",            DBI::SQL_VARCHAR, 'NVARCHAR2',true,  10 * cfrm, nil, false,false,false,nil],
+       [ora80, "RAW(10)",                  DBI::SQL_VARBINARY, 'RAW',    true,         10, nil, false,false,false,nil],
+       [ora81, "CLOB",                     DBI::SQL_CLOB,    'CLOB',     true,       4000, nil, false,false,false,nil],
+       [ora81, "NCLOB",                    DBI::SQL_CLOB,    'NCLOB',    true,       4000, nil, false,false,false,nil],
+       [ora80, "BLOB",                     DBI::SQL_BLOB,    'BLOB',     true,       4000, nil, false,false,false,nil],
+       [ora80, "BFILE",                    DBI::SQL_BLOB,    'BFILE',    true,       4000, nil, false,false,false,nil],
+       [ora80, "NUMBER",                   DBI::SQL_NUMERIC, 'NUMBER',   true,         38, nil, false,false,false,nil],
+       [ora80, "NUMBER(10)",               DBI::SQL_NUMERIC, 'NUMBER',   true,         10,   0, false,false,false,nil],
+       [ora80, "NUMBER(10,2)",             DBI::SQL_NUMERIC, 'NUMBER',   true,         10,   2, false,false,false,nil],
+       [ora80, "FLOAT",                    DBI::SQL_FLOAT,   'FLOAT',    true, (126 * 0.30103).ceil, nil, false,false,false,nil],
+       [ora80, "FLOAT(10)",                DBI::SQL_FLOAT,   'FLOAT',    true, (10 * 0.30103).ceil, nil, false,false,false,nil],
+       [ora101,"BINARY_FLOAT",             DBI::SQL_FLOAT,   'BINARY_FLOAT', true,      7, nil, false,false,false,nil],
+       [ora101,"BINARY_DOUBLE",            DBI::SQL_DOUBLE,  'BINARY_DOUBLE', true,    16, nil, false,false,false,nil],
+       [ora80, "DATE",                     DBI::SQL_DATE,    'DATE',     true,         19, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP",                DBI::SQL_TIMESTAMP, 'TIMESTAMP', true,  20 + 6, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP(9)",             DBI::SQL_TIMESTAMP, 'TIMESTAMP', true,  20 + 9, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP WITH TIME ZONE",          DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH TIME ZONE', true,  27 + 6, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP(9) WITH TIME ZONE",       DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH TIME ZONE', true,  27 + 9, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP WITH LOCAL TIME ZONE",    DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH LOCAL TIME ZONE', true,  20 + 6, nil, false,false,false,nil],
+       [ora91, "TIMESTAMP(9) WITH LOCAL TIME ZONE", DBI::SQL_TIMESTAMP, 'TIMESTAMP WITH LOCAL TIME ZONE', true,  20 + 9, nil, false,false,false,nil],
+       [ora91, "INTERVAL YEAR TO MONTH",      DBI::SQL_OTHER, 'INTERVAL YEAR TO MONTH', true, 2 + 3, nil, false,false,false,nil],
+       [ora91, "INTERVAL YEAR(4) TO MONTH",   DBI::SQL_OTHER, 'INTERVAL YEAR TO MONTH', true, 4 + 3, nil, false,false,false,nil],
+       [ora91, "INTERVAL DAY TO SECOND",      DBI::SQL_OTHER, 'INTERVAL DAY TO SECOND', true, 2 + 10 + 6, nil, false,false,false,nil],
+       [ora91, "INTERVAL DAY(4) TO SECOND(9)",DBI::SQL_OTHER, 'INTERVAL DAY TO SECOND', true, 4 + 10 + 9, nil, false,false,false,nil],
       ]
 
     coldef.reject! do |c| c[0] > $oracle_version end
@@ -288,17 +318,25 @@
        ["TABTYPE",  DBI::SQL_VARCHAR,'VARCHAR2',true,     7,       nil,  false,  false,  false, nil],
        ["CLUSTERID",DBI::SQL_NUMERIC,'NUMBER',  true,    38,       nil,  false,  false,  false, nil],
       ]
-    @dbh.columns('tab').each_with_index do |ci, i|
-      assert_equal(coldef[i][0], ci['name'],      "'#{coldef[i][0]}': name")
-      assert_equal(coldef[i][1], ci['sql_type'],  "'#{coldef[i][0]}': sql_type")
-      assert_equal(coldef[i][2], ci['type_name'], "'#{coldef[i][0]}': type_name")
-      assert_equal(coldef[i][3], ci['nullable'],  "'#{coldef[i][0]}': nullable")
-      assert_equal(coldef[i][4], ci['precision'], "'#{coldef[i][0]}': precision")
-      assert_equal(coldef[i][5], ci['scale'],     "'#{coldef[i][0]}': scale")
-      assert_equal(coldef[i][6], ci['indexed'],   "'#{coldef[i][0]}': indexed")
-      assert_equal(coldef[i][7], ci['primary'],   "'#{coldef[i][0]}': primary")
-      assert_equal(coldef[i][8], ci['unique'],    "'#{coldef[i][0]}': unique")
-      assert_equal(coldef[i][9], ci['default'],    "'#{coldef[i][0]}': default")
+    begin
+      @dbh.columns('tab').each_with_index do |ci, i|
+        assert_equal(coldef[i][0], ci['name'],      "'#{coldef[i][0]}': name")
+        assert_equal(coldef[i][1], ci['sql_type'],  "'#{coldef[i][0]}': sql_type")
+        assert_equal(coldef[i][2], ci['type_name'], "'#{coldef[i][0]}': type_name")
+        assert_equal(coldef[i][3], ci['nullable'],  "'#{coldef[i][0]}': nullable")
+        assert_equal(coldef[i][4], ci['precision'], "'#{coldef[i][0]}': precision")
+        assert_equal(coldef[i][5], ci['scale'],     "'#{coldef[i][0]}': scale")
+        assert_equal(coldef[i][6], ci['indexed'],   "'#{coldef[i][0]}': indexed")
+        assert_equal(coldef[i][7], ci['primary'],   "'#{coldef[i][0]}': primary")
+        assert_equal(coldef[i][8], ci['unique'],    "'#{coldef[i][0]}': unique")
+        assert_equal(coldef[i][9], ci['default'],    "'#{coldef[i][0]}': default")
+      end
+    rescue RuntimeError
+      if $oracle_version < OCI8::ORAVER_8_1
+        assert_equal("This feature is unavailable on Oracle 8.0", $!.to_s)
+      else
+        raise
+      end
     end
 
     @dbh.execute("SELECT * FROM tab").column_info.each_with_index do |ci, i|

Modified: trunk/ruby-oci8/test/test_metadata.rb
===================================================================
--- trunk/ruby-oci8/test/test_metadata.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/test/test_metadata.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -35,7 +35,7 @@
 
     ora80 = OCI8::ORAVER_8_0
     ora81 = OCI8::ORAVER_8_1
-    ora91 = OCI8::ORAVER_8_1
+    ora91 = OCI8::ORAVER_9_1
     ora101 = OCI8::ORAVER_10_1
     coldef =
       [

Modified: trunk/ruby-oci8/test/test_oci8.rb
===================================================================
--- trunk/ruby-oci8/test/test_oci8.rb	2008-08-28 06:03:07 UTC (rev 286)
+++ trunk/ruby-oci8/test/test_oci8.rb	2008-08-31 14:11:39 UTC (rev 287)
@@ -24,14 +24,53 @@
     drop_table('test_rename_table')
   end
 
+  # USE_DYNAMIC_FETCH doesn't work well...
+  # This test is disabled.
+  def _test_long_type
+    drop_table('test_table')
+    @conn.exec('CREATE TABLE test_table (id number(38), lng long)')
+    test_data1 = 'a' * 70000
+    test_data2 = 'b' * 3000
+    test_data3 = nil
+    test_data4 = 'c' * 70000
+    @conn.exec('insert into test_table values (:1, :2)', 1, test_data1)
+    @conn.exec('insert into test_table values (:1, :2)', 2, [test_data2, :long])
+    @conn.exec('insert into test_table values (:1, :2)', 3, [nil, :long])
+    @conn.exec('insert into test_table values (:1, :2)', 4, [test_data4, :long])
+
+    [8000, 65535, 65536, 80000].each do |read_len|
+      @conn.long_read_len = read_len
+      cursor = @conn.parse('SELECT lng from test_table order by id')
+      cursor.exec
+      assert_equal(test_data1, cursor.fetch[0])
+      assert_equal(test_data2, cursor.fetch[0])
+      assert_equal(test_data3, cursor.fetch[0])
+      assert_equal(test_data4, cursor.fetch[0])
+      cursor.close
+    end
+    drop_table('test_table')
+  end
+
   def test_long_type
+    @conn.long_read_len = 80000
     drop_table('test_table')
-    sql = <<-EOS
-CREATE TABLE test_table
-  (C CHAR(10) NOT NULL)
-EOS
-    @conn.exec(sql)
-    @conn.exec("SELECT column_name, data_default FROM all_tab_columns where owner = '#{$dbuser}' and table_name = 'TEST_TABLE'")
+    @conn.exec('CREATE TABLE test_table (id number(38), lng long)')
+    test_data1 = 'a' * 70000
+    test_data2 = 'b' * 3000
+    test_data3 = nil
+    test_data4 = 'c' * 70000
+    @conn.exec('insert into test_table values (:1, :2)', 1, test_data1)
+    @conn.exec('insert into test_table values (:1, :2)', 2, [test_data2, :long])
+    @conn.exec('insert into test_table values (:1, :2)', 3, [nil, :long])
+    @conn.exec('insert into test_table values (:1, :2)', 4, [test_data4, :long])
+
+    cursor = @conn.parse('SELECT lng from test_table order by id')
+    cursor.exec
+    assert_equal(test_data1, cursor.fetch[0])
+    assert_equal(test_data2, cursor.fetch[0])
+    assert_equal(test_data3, cursor.fetch[0])
+    assert_equal(test_data4, cursor.fetch[0])
+    cursor.close
     drop_table('test_table')
   end
 




More information about the ruby-oci8-commit mailing list