[ruby-oci8-commit] [399] trunk/ruby-oci8: * ext/oci8/metadata.c: fix a private method

nobody at rubyforge.org nobody at rubyforge.org
Sun Jun 13 05:26:16 EDT 2010


Revision: 399
Author:   kubo
Date:     2010-06-13 05:26:15 -0400 (Sun, 13 Jun 2010)

Log Message:
-----------
* ext/oci8/metadata.c: fix a private method
    OCI8::Metadata::Base#__param to return nil when the specified
    attribute is NULL.
* lib/oci8/metadata.rb: add rdoc comment of OCI8::Metadata::Type
    and fix other typos. change OCI8::Metadata::Schema#all_objects
    not to raise "ORA-24372: invalid object for describe" by
    invalid objects.
* test/test_metadata.rb: add tests for OCI8::Metadata::Type.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/metadata.c
    trunk/ruby-oci8/lib/oci8/metadata.rb
    trunk/ruby-oci8/test/test_metadata.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-06-11 10:24:41 UTC (rev 398)
+++ trunk/ruby-oci8/ChangeLog	2010-06-13 09:26:15 UTC (rev 399)
@@ -1,3 +1,13 @@
+2010-06-13  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/metadata.c: fix a private method
+	    OCI8::Metadata::Base#__param to return nil when the specified
+	    attribute is NULL.
+	* lib/oci8/metadata.rb: add rdoc comment of OCI8::Metadata::Type
+	    and fix other typos. change OCI8::Metadata::Schema#all_objects
+	    not to raise "ORA-24372: invalid object for describe" by
+	    invalid objects.
+	* test/test_metadata.rb: add tests for OCI8::Metadata::Type.
+
 2010-06-11  KUBO Takehiro  <kubo at jiubao.org>
 	* lib/oci8/metadata.rb: rename OCI8::Metabase::ProcBase to
 	    OCI8::Metabase::Subprogram, add #is_standalone? and change

Modified: trunk/ruby-oci8/ext/oci8/metadata.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/metadata.c	2010-06-11 10:24:41 UTC (rev 398)
+++ trunk/ruby-oci8/ext/oci8/metadata.c	2010-06-13 09:26:15 UTC (rev 399)
@@ -69,6 +69,16 @@
     return Qnil;
 }
 
+/*
+ * call-seq:
+ *   __param(attr_type) -> metadata information or nil
+ *
+ * Gets the value of the attribute specified by +attr_type+
+ * as an instance of an OCI8::Metadata::Base's subclass.
+ *
+ * <b>Caution:</b> If the specified attr_type's datatype is not a
+ * metadata, it causes a segmentation fault.
+ */
 static VALUE metadata_get_param(VALUE self, VALUE idx)
 {
     oci8_metadata_t *md = DATA_PTR(self);
@@ -76,11 +86,15 @@
     OCIParam *value;
     ub4 size = sizeof(value);
 
-    /* remote call? */
+    Check_Type(idx, T_FIXNUM);
+    /* Is it remote call? */
     oci_lc(OCIAttrGet_nb(svcctx, md->base.hp.ptr, md->base.type, &value, &size, FIX2INT(idx), oci8_errhp));
     if (size != sizeof(OCIParam *)) {
         rb_raise(rb_eRuntimeError, "Invalid attribute size. expect %d, but %d", (sb4)sizeof(OCIParam *), size);
     }
+    if (value == NULL) {
+        return Qnil;
+    }
     return oci8_metadata_create(value, md->svc, self);
 }
 

Modified: trunk/ruby-oci8/lib/oci8/metadata.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/metadata.rb	2010-06-11 10:24:41 UTC (rev 398)
+++ trunk/ruby-oci8/lib/oci8/metadata.rb	2010-06-13 09:26:15 UTC (rev 399)
@@ -13,7 +13,7 @@
   # data are called metadata and retrived as an instance of
   # OCI8::Metadata::Base's subclass.
   #
-  # List of methots which return OCI8::Metadata::Base.
+  # List of methods which return OCI8::Metadata::Base.
   # * OCI8#describe_any(object_name)
   # * OCI8#describe_table(table_name, table_only = false)
   # * OCI8#describe_view(view_name)
@@ -29,7 +29,7 @@
   # * OCI8::Metadata::Type#order_method
   # * OCI8::Metadata::Type#collection_element
   #
-  # List of methots which return an array of OCI8::Metadata::Base.
+  # List of methods which return an array of OCI8::Metadata::Base.
   # * OCI8::Cursor#column_metadata
   # * OCI8::Metadata::Database#schemas
   # * OCI8::Metadata::Schema#all_objects
@@ -62,7 +62,7 @@
       # call-seq:
       #   obj_id -> integer or nil
       #
-      # Returns an object ID, which is the same as the value of the
+      # Returns the object ID, which is the same as the value of the
       # OBJECT_ID column from ALL_OBJECTS. It returns +nil+
       # if the database object doesn't have ID.
       def obj_id
@@ -72,7 +72,8 @@
       # call-seq:
       #   obj_name -> string
       #
-      # Retruns object name; table name, view name, procedure name, etc.
+      # Retruns the object name such as table name, view name,
+      # procedure name, and so on.
       def obj_name
         attr_get_string(OCI_ATTR_OBJ_NAME)
       end
@@ -80,7 +81,7 @@
       # call-seq:
       #   obj_schema -> string
       #
-      # Retruns a schema name. It returns +nil+
+      # Retruns the schema name. It returns +nil+
       # if the database object is not defined just under a schema.
       def obj_schema
         attr_get_string(OCI_ATTR_OBJ_SCHEMA)
@@ -384,10 +385,10 @@
       private :list_columns
 
       # call-seq:
-      #   type_methods -> an OCI8::Metadata::Type or nil
+      #   type_metadata -> an OCI8::Metadata::Type or nil
       #
       # Retruns an instance of OCI8::Metadata::Type if the table is an
-      # {object table}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjint.htm#sthref48].
+      # {object table}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjint.htm#sthref61].
       # Otherwise, +nil+.
       def type_metadata
         __type_metadata(OCI8::Metadata::Type) if is_typed?
@@ -476,10 +477,9 @@
       end
 
       # call-seq:
-      #   columns -> an array of OCI8::Metadata::Column
+      #   columns -> list of column information
       #
-      # Returns an array of {column information}[link:OCI8/Metadata/Column.html]
-      # of the table.
+      # Returns an array of OCI8::Metadata::Column of the table.
       def columns
         @columns ||= list_columns.to_a
       end
@@ -537,10 +537,9 @@
       #end
 
       # call-seq:
-      #   columns -> an array of OCI8::Metadata::Column
+      #   columns -> list of column information
       #
-      # Returns an array of {column information}[link:OCI8/Metadata/Column.html]
-      # of the table.
+      # Returns an array of OCI8::Metadata::Column of the table.
       def columns
         @columns ||= list_columns.to_a
       end
@@ -606,10 +605,9 @@
       end
 
       # call-seq:
-      #   arguments -> an array of OCI8::Metadata::Argument
+      #   arguments -> list of argument information
       #
-      # Returns an array of {argument information}[link:OCI8/Metadata/Argument.html]
-      # of the subprogram.
+      # Returns an array of OCI8::Metadata::Argument of the subprogram.
       # If it is a function, the first array element is information of its return type.
       def arguments
         @arguments ||= list_arguments.to_a
@@ -677,16 +675,19 @@
       private :list_subprograms
 
       # call-seq:
-      #   is_invoker_rights? -> <i>true</i> or <i>false</i>
+      #   is_invoker_rights? -> true or false
       #
-      # Returns <i>true</i> if the package subprograms have
-      # [invoker's rights][http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/subprograms.htm#i18574].
-      # Otherwise, <i>false</i>.
+      # Returns +true+ if the package subprograms have
+      # {invoker's rights}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/subprograms.htm#i18574].
+      # Otherwise, +false+.
       def is_invoker_rights?
         attr_get_ub1(OCI_ATTR_IS_INVOKER_RIGHTS) != 0
       end
 
-      # array of Procedure or Function objects.
+      # call-seq:
+      #   subprograms -> array
+      #
+      # Returns an array of Function and Procedure defined within the Package.
       def subprograms
         @subprograms ||= list_subprograms.to_a.each do |prog|
           prog.instance_variable_set(:@is_standalone, false)
@@ -694,9 +695,9 @@
       end
     end
 
-    # Metadata for a type.
+    # Information about types
     #
-    # This is returned by:
+    # An instance of this class is returned by:
     # * OCI8#describe_any(name)
     # * OCI8#describe_type(name)
     # * OCI8::Metadata::Schema#all_objects
@@ -711,139 +712,250 @@
         self
       end
 
-      # typecode. :object or :named_collection
+      # call-seq:
+      #   typecode -> :named_type or :named_collection
+      #
+      # Returns +:named_type+ if the type is an object type,
+      # +:named_collection+ if it is a nested table or a varray.
       def typecode
         __typecode(OCI_ATTR_TYPECODE)
       end
 
-      # typecode of collection if type is collection. nil if otherwise.
+      # call-seq:
+      #   collection_typecode -> :table, :varray or nil
+      #
+      # Returns +:table+ if the type is a nested table,
+      # +:varray+ if it is a varray. Otherwise, +nil+.
       def collection_typecode
         __typecode(OCI_ATTR_COLLECTION_TYPECODE) if typecode == :named_collection
       end
 
-      # indicates this is an incomplete type
+      # call-seq:
+      #   is_incomplete_type? -> boolean
+      #
+      # Returns +true+ if the type is an
+      # {incomplete type}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjmng.htm#i1003083],
+      # which is used for {forward declaration}[http://en.wikipedia.org/wiki/Forward_declaration].
+      # Otherwise, +false+.
       def is_incomplete_type?
-        __boolean(OCI_ATTR_IS_INCOMPLETE_TYPE)
+        attr_get_ub1(OCI_ATTR_IS_INCOMPLETE_TYPE) != 0
       end
 
-      # indicates this is a system type
-      def is_system_type?
-        __boolean(OCI_ATTR_IS_SYSTEM_TYPE)
+      # call-seq:
+      #   is_system_type? -> boolean
+      #
+      # Always returns +false+ because there is no way to create
+      # a type metadata object for a system type such as +NUMBER+,
+      # +CHAR+ and +VARCHAR+.
+      def is_system_type? # :nodoc:
+        attr_get_ub1(OCI_ATTR_IS_SYSTEM_TYPE) != 0
       end
 
-      # indicates this is a predefined type
-      def is_predefined_type?
-        __boolean(OCI_ATTR_IS_PREDEFINED_TYPE)
+      # call-seq:
+      #   is_predefined_type? -> boolean
+      #
+      # Always returns +false+.
+      #--
+      # I don't know the definition of predefined type...
+      def is_predefined_type? # :nodoc:
+        attr_get_ub1(OCI_ATTR_IS_PREDEFINED_TYPE) != 0
       end
 
-      # indicates this is a transient type
-      def is_transient_type?
-        __boolean(OCI_ATTR_IS_TRANSIENT_TYPE)
+      # call-seq:
+      #   is_transient_type? -> boolean
+      #
+      # Always returns +false+ because there is no way to create
+      # a type metadata object for a transient type, which is a type
+      # dynamically created by C API.
+      def is_transient_type? # :nodoc:
+        attr_get_ub1(OCI_ATTR_IS_TRANSIENT_TYPE) != 0
       end
 
-      # indicates this is a system-generated type
-      def is_system_generated_type?
-        __boolean(OCI_ATTR_IS_SYSTEM_GENERATED_TYPE)
+      # call-seq:
+      #   is_predefined_type? -> boolean
+      #
+      # Always returns +false+.
+      #--
+      # I don't know the definition of system generated type.
+      # What is different with system type and predefined type.
+      def is_system_generated_type? # :nodoc:
+        attr_get_ub1(OCI_ATTR_IS_SYSTEM_GENERATED_TYPE) != 0
       end
 
-      # indicates this type contains a nested table attribute.
+      # call-seq:
+      #   has_nested_table? -> boolean
+      #
+      # Returns +true+ if the type is a nested table or
+      # has a nested table attribute.
+      # Otherwise, +false+.
       def has_nested_table?
-        __boolean(OCI_ATTR_HAS_NESTED_TABLE)
+        attr_get_ub1(OCI_ATTR_HAS_NESTED_TABLE) != 0
       end
 
-      # indicates this type contains a LOB attribute
+      # call-seq:
+      #   has_lob? -> boolean
+      #
+      # Returns +true+ if the type has a CLOB, NCLOB or BLOB
+      # attribute.
+      # Otherwise, +false+.
       def has_lob?
-        __boolean(OCI_ATTR_HAS_LOB)
+        attr_get_ub1(OCI_ATTR_HAS_LOB) != 0
       end
 
-      # indicates this type contains a BFILE attribute
+      # call-seq:
+      #   has_file? -> boolean
+      #
+      # Returns +true+ if the type has a BFILE attribute.
+      # Otherwise, +false+.
       def has_file?
-        __boolean(OCI_ATTR_HAS_FILE)
+        attr_get_ub1(OCI_ATTR_HAS_FILE) != 0
       end
 
-      # returns OCI8::Metadata::Collection if type is collection. nil if otherwise.
+      # call-seq:
+      #   collection_element -> element information of the collection type
+      #
+      # Returns an OCI8::Metadata::Collection if the type is a nested
+      # table or a varray.
+      # Otherwise, +nil+.
       def collection_element
         __param(OCI_ATTR_COLLECTION_ELEMENT) if typecode == :named_collection
       end
 
-      # number of type attributes
+      # call-seq:
+      #   num_type_attrs -> integer
+      #
+      # Returns number of type attributes.
       def num_type_attrs
         attr_get_ub2(OCI_ATTR_NUM_TYPE_ATTRS)
       end
 
       # list of type attributes
-      def list_type_attrs
+      def list_type_attrs # :nodoc:
         __param(OCI_ATTR_LIST_TYPE_ATTRS)
       end
       private :list_type_attrs
 
-      # number of type methods
+      # call-seq:
+      #   num_type_methods -> integer
+      #
+      # Returns number of type methods.
       def num_type_methods
         attr_get_ub2(OCI_ATTR_NUM_TYPE_METHODS)
       end
 
       # list of type methods
-      def list_type_methods
+      def list_type_methods # :nodoc:
         __param(OCI_ATTR_LIST_TYPE_METHODS)
       end
       private :list_type_methods
 
-      # map method of type
+      # call-seq:
+      #   map_method -> map method information
+      #
+      # Returns an instance of OCI8::Metadata::TypeMethod of a
+      # {map method}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjbas.htm#sthref180]
+      # if it is defined in the type. Otherwise, +nil+.
       def map_method
         __param(OCI_ATTR_MAP_METHOD)
       end
 
-      # order method of type
+      # call-seq:
+      #   order_method -> order method information
+      #
+      # Returns an instance of OCI8::Metadata::TypeMethod of a
+      # {order method}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjbas.htm#sthref185]
+      # if it is defined in the type. Otherwise, +nil+.
       def order_method
         __param(OCI_ATTR_ORDER_METHOD)
       end
 
-      # indicates the type has invoker's rights
+      # call-seq:
+      #   is_invoker_rights? -> boolean
+      #
+      # Returns +true+ if the type has
+      # {invoker's rights}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/appdev.111/b28371/adobjdes.htm#ADOBJ00810].
+      # Otherwise, +false+.
       def is_invoker_rights?
-        __boolean(OCI_ATTR_IS_INVOKER_RIGHTS)
+        attr_get_ub1(OCI_ATTR_IS_INVOKER_RIGHTS) != 0
       end
 
-      # type name
+      # call-seq:
+      #   name -> string
+      #
+      # Returns the type name.
       def name
         attr_get_string(OCI_ATTR_NAME)
       end
 
-      # schema name where the type has been created
+      # call-seq:
+      #   schema_name -> string
+      #
+      # Returns the schema name where the type has been created.
       def schema_name
         attr_get_string(OCI_ATTR_SCHEMA_NAME)
       end
 
-      # indicates this is a final type
+      # call-seq:
+      #   is_final_type? -> boolean
+      #
+      # Returns +true+ if the type is a
+      # {final type}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjbas.htm#CIHFBHFC];
+      # in other words, subtypes cannot be derived from the type.
+      # Otherwise, +false+.
       def is_final_type?
-        __boolean(OCI_ATTR_IS_FINAL_TYPE)
+        attr_get_ub1(OCI_ATTR_IS_FINAL_TYPE) != 0
       end
 
-      # indicates this is an instantiable type
+      # call-seq:
+      #   is_instantiable_type? -> boolean
+      #
+      # Returns +true+ if the type is not declared without
+      # {<tt>NOT INSTANTIABLE</tt>}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjbas.htm#i456586].
+      # Otherwise, +false+.
       def is_instantiable_type?
-        __boolean(OCI_ATTR_IS_INSTANTIABLE_TYPE)
+        attr_get_ub1(OCI_ATTR_IS_INSTANTIABLE_TYPE) != 0
       end
 
-      # indicates this is a subtype
+      # call-seq:
+      #   is_subtype? -> boolean
+      #
+      # Returns +true+ if the type is a
+      # {subtype}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28371/adobjbas.htm#BCFJJADG].
+      # Otherwise, +false+.
       def is_subtype?
-        __boolean(OCI_ATTR_IS_SUBTYPE)
+        attr_get_ub1(OCI_ATTR_IS_SUBTYPE) != 0
       end
 
-      # supertype's schema name
+      # call-seq:
+      #   supertype_schema_name -> string or nil
+      #
+      # Returns the supertype's schema name if the type is a subtype.
+      # Otherwise, +nil+.
       def supertype_schema_name
         attr_get_string(OCI_ATTR_SUPERTYPE_SCHEMA_NAME) if is_subtype?
       end
 
-      # supertype's name
+      # call-seq:
+      #   supertype_name -> string or nil
+      #
+      # Returns the supertype's name if the type is a subtype.
+      # Otherwise, +nil+.
       def supertype_name
         attr_get_string(OCI_ATTR_SUPERTYPE_NAME) if is_subtype?
       end
 
-      # array of TypeAttr objects.
+      # call-seq:
+      #   type_attrs -> list of attribute information
+      #
+      # Returns an array of OCI8::Metadata::TypeAttr which the type has.
       def type_attrs
         @type_attrs ||= list_type_attrs.to_a
       end
 
-      # array of TypeMethod objects.
+      # call-seq:
+      #   type_methods -> list of method information
+      #
+      # Returns an array of OCI8::Metadata::TypeMethod which the type has.
       def type_methods
         @type_methods ||= list_type_methods.to_a
       end
@@ -1662,11 +1774,16 @@
               case elem
               when OCI8::Metadata::Type
                 # to avoid a segmentation fault
-                __con.describe_type(elem.obj_schema + '.' + elem.obj_name)
+                begin
+                  __con.describe_type(elem.obj_schema + '.' + elem.obj_name)
+                rescue OCIError
+                  # ignore ORA-24372: invalid object for describe
+                  raise if $!.code != 24372
+                end
               else
                 elem
               end
-            end
+            end.compact
           end
       end
 

Modified: trunk/ruby-oci8/test/test_metadata.rb
===================================================================
--- trunk/ruby-oci8/test/test_metadata.rb	2010-06-11 10:24:41 UTC (rev 398)
+++ trunk/ruby-oci8/test/test_metadata.rb	2010-06-13 09:26:15 UTC (rev 399)
@@ -12,6 +12,21 @@
     @conn.logoff
   end
 
+  def drop_type(name, drop_body = false)
+    if drop_body
+      begin
+        @conn.exec("DROP TYPE BODY #{name}")
+      rescue OCIError
+        raise if $!.code != 4043
+      end
+    end
+    begin
+      @conn.exec("DROP TYPE #{name}")
+    rescue OCIError
+      raise if $!.code != 4043
+    end
+  end
+
   def test_metadata
     if $oracle_version < OCI8::ORAVER_8_1
       begin
@@ -686,4 +701,308 @@
       assert_equal(OCI8::Metadata::Procedure, desc.subprograms[0].class)
     end
   end # test_package_metadata
+
+  def test_type_metadata
+    drop_type('TEST_TYPE_ORDER_METHOD')
+    drop_type('TEST_TYPE_MAP_METHOD')
+    drop_type('TEST_TYPE_HAS_BFILE')
+    drop_type('TEST_TYPE_HAS_BLOB')
+    drop_type('TEST_TYPE_HAS_NCLOB')
+    drop_type('TEST_TYPE_HAS_CLOB')
+    drop_type('TEST_TYPE_INCOMPLETE')
+    drop_type('TEST_TYPE_GRANDCHILD')
+    drop_type('TEST_TYPE_VARRAY')
+    drop_type('TEST_TYPE_NESTEAD_TABLE')
+    drop_type('TEST_TYPE_CHILD')
+    drop_type('TEST_TYPE_PARENT')
+    expected_values = []
+
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_parent AS OBJECT (
+  col1 number(38,0),
+  col2 varchar2(60)
+)
+NOT INSTANTIABLE
+NOT FINAL
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_PARENT',
+      :typecode => :named_type,
+      :collection_typecode => nil,
+      :is_incomplete_type? => false,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => false,
+      :has_lob? => false,
+      :has_file? => false,
+      :collection_element => nil,
+      :num_type_attrs => 2,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => false,
+      :is_instantiable_type? => false,
+      :is_subtype? => false,
+      :supertype_schema_name => nil,
+      :supertype_name => nil,
+      :type_attrs => [:array, 2, OCI8::Metadata::TypeAttr],
+      :type_methods => [:array, 0],
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_child UNDER test_type_parent (
+  lob BLOB
+)
+NOT FINAL
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_CHILD',
+      :typecode => :named_type,
+      :collection_typecode => nil,
+      :is_incomplete_type? => false,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => false,
+      :has_lob? => true,
+      :has_file? => false,
+      :collection_element => nil,
+      :num_type_attrs => 3,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => false,
+      :is_instantiable_type? => true,
+      :is_subtype? => true,
+      :supertype_schema_name => @conn.username,
+      :supertype_name => 'TEST_TYPE_PARENT',
+      :type_attrs => [:array, 3, OCI8::Metadata::TypeAttr],
+      :type_methods => [:array, 0],
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_nestead_table AS TABLE OF test_type_child
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_NESTEAD_TABLE',
+      :typecode => :named_collection,
+      :collection_typecode => :table,
+      :is_incomplete_type? => false,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => true,
+      :has_lob? => true,
+      :has_file? => false,
+      :collection_element => [:type, OCI8::Metadata::Collection],
+      :num_type_attrs => 0,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => true,
+      :is_instantiable_type? => true,
+      :is_subtype? => false,
+      :supertype_schema_name => nil,
+      :supertype_name => nil,
+      :type_attrs => [:array, 0],
+      :type_methods => [:array, 0],
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_varray AS VARRAY(10) OF test_type_child
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_VARRAY',
+      :typecode => :named_collection,
+      :collection_typecode => :varray,
+      :is_incomplete_type? => false,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => false,
+      :has_lob? => true,
+      :has_file? => false,
+      :collection_element => [:type, OCI8::Metadata::Collection],
+      :num_type_attrs => 0,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => true,
+      :is_instantiable_type? => true,
+      :is_subtype? => false,
+      :supertype_schema_name => nil,
+      :supertype_name => nil,
+      :type_attrs => [:array, 0],
+      :type_methods => [:array, 0],
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_grandchild UNDER test_type_child (
+  table_column test_type_nestead_table,
+  file_column BFILE
+)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_GRANDCHILD',
+      :typecode => :named_type,
+      :collection_typecode => nil,
+      :is_incomplete_type? => false,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => true,
+      :has_lob? => true,
+      :has_file? => true,
+      :collection_element => nil,
+      :num_type_attrs => 5,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => true,
+      :is_instantiable_type? => true,
+      :is_subtype? => true,
+      :supertype_schema_name => @conn.username,
+      :supertype_name => 'TEST_TYPE_CHILD',
+      :type_attrs => [:array, 5, OCI8::Metadata::TypeAttr],
+      :type_methods => [:array, 0],
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_incomplete
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_INCOMPLETE',
+      :typecode => :named_type,
+      :collection_typecode => nil,
+      :is_incomplete_type? => true,
+      :is_system_type? => false,
+      :is_predefined_type? => false,
+      :is_transient_type? => false,
+      :is_system_generated_type? => false,
+      :has_nested_table? => false,
+      :has_lob? => false,
+      :has_file? => false,
+      :collection_element => nil,
+      :num_type_attrs => 0,
+      :num_type_methods => 0,
+      :map_method => nil,
+      :order_method => nil,
+      :is_invoker_rights? => false,
+      :is_final_type? => true,
+      :is_instantiable_type? => true,
+      :is_subtype? => false,
+      :supertype_schema_name => nil,
+      :supertype_name => nil,
+      :type_attrs => [:array, 0],
+      :type_methods => [:array, 0],
+    }
+
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_has_clob AS OBJECT (lob CLOB)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_HAS_CLOB',
+      :has_lob? => true,
+      :has_file? => false,
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_has_nclob AS OBJECT (lob NCLOB)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_HAS_NCLOB',
+      :has_lob? => true,
+      :has_file? => false,
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_has_blob AS OBJECT (lob BLOB)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_HAS_BLOB',
+      :has_lob? => true,
+      :has_file? => false,
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_has_bfile AS OBJECT (lob BFILE)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_HAS_BFILE',
+      :has_lob? => false,
+      :has_file? => true,
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_map_method AS OBJECT (
+  x integer,
+  y integer,
+  MAP MEMBER FUNCTION area RETURN NUMBER
+)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_MAP_METHOD',
+      :map_method => [:type, OCI8::Metadata::TypeMethod],
+      :order_method => nil,
+    }
+    @conn.exec(<<-EOS)
+CREATE TYPE test_type_order_method AS OBJECT (
+  x integer,
+  y integer,
+  ORDER MEMBER FUNCTION match(l test_type_order_method) RETURN INTEGER
+)
+EOS
+    expected_values << {
+      :obj_name => 'TEST_TYPE_ORDER_METHOD',
+      :map_method => nil,
+      :order_method => [:type, OCI8::Metadata::TypeMethod],
+    }
+
+    expected_values.each do |elem|
+      [
+       @conn.describe_any(elem[:obj_name]),
+       @conn.describe_type(elem[:obj_name]),
+       @conn.describe_schema(@conn.username).objects.detect do |obj|
+         obj.obj_name == elem[:obj_name]
+       end,
+      ].each do |desc|
+        assert_object_id(elem[:obj_name], desc.obj_id)
+        assert_equal(@conn.username, desc.obj_schema)
+        assert_equal(elem[:obj_name], desc.name)
+        assert_equal(@conn.username, desc.schema_name)
+
+        elem.each do |key, val|
+          if val.is_a? Array
+            case val[0]
+            when :array
+              assert_equal(Array, desc.send(key).class, elem[:obj_name] + '.' + key)
+              assert_equal(val[1], desc.send(key).length)
+              assert_equal(val[2], desc.send(key)[0].class) if val[1] > 0
+            when :type
+              assert_equal(val[1], desc.send(key).class, elem[:obj_name] + '.' + key)
+            else
+              raise "Invalid test case: #{elem[:obj_name]}.#{key} : #{val[0]}"
+            end
+          else
+            assert_equal(val, desc.send(key), elem[:obj_name] + '.' + key)
+          end
+        end
+      end
+    end
+
+    drop_type('TEST_TYPE_ORDER_METHOD')
+    drop_type('TEST_TYPE_MAP_METHOD')
+    drop_type('TEST_TYPE_HAS_BFILE')
+    drop_type('TEST_TYPE_HAS_BLOB')
+    drop_type('TEST_TYPE_HAS_NCLOB')
+    drop_type('TEST_TYPE_HAS_CLOB')
+    drop_type('TEST_TYPE_INCOMPLETE')
+    drop_type('TEST_TYPE_GRANDCHILD')
+    drop_type('TEST_TYPE_VARRAY')
+    drop_type('TEST_TYPE_NESTEAD_TABLE')
+    drop_type('TEST_TYPE_CHILD')
+    drop_type('TEST_TYPE_PARENT')
+  end # test_type_metadata
 end # TestMetadata




More information about the ruby-oci8-commit mailing list