AR JDBC Oracle does not handle writing of LOBS correctly.
---------------------------------------------------------

                 Key: JRUBY-1223
                 URL: http://jira.codehaus.org/browse/JRUBY-1223
             Project: JRuby
          Issue Type: Bug
          Components: ActiveRecord-JDBC
         Environment: Oracle 10G
            Reporter: Michael Schubert
            Assignee: Thomas E Enebo


Currently with AR JDBC when you save a record to a table that has a BLOB or 
CLOB column, it correctly substitutes the value on the initial save with either 
empty_blob() or empty_clob() but it never implemented the after_save mechanism 
used by Rails w/ OCI to use an after save to write back.

Below is the original code from rails that is missing:

{code:title=oracle_adapter.rb|borderStyle=solid}
...
      # After setting large objects to empty, select the OCI8::LOB
      # and write back the data.
      after_save :write_lobs
      def write_lobs() #:nodoc:
        if connection.is_a?(ConnectionAdapters::OracleAdapter)
          self.class.columns.select { |c| c.sql_type =~ /LOB$/i }.each { |c|
            value = self[c.name]
            value = value.to_yaml if unserializable_attribute?(c.name, c)
            next if value.nil?  || (value == '')
            lob = connection.select_one(
              "SELECT #{c.name} FROM #{self.class.table_name} WHERE 
#{self.class.primary_key} = #{quote_value(id)}",
              'Writable Large Object')[c.name]
            lob.write value
          }
        end
      end

      private :write_lobs
...
{code:}

However the last line, "lob.write value" will only work if the return from 
connection.select_one is actually a special object created by the private 
_select method in the original oracle_adapter.rb, which has logic that is 
currently not implemented. First pass I made at trying to fix this stopped me 
here since it looks like you may need to have @connection.execute_query handle 
the logic below (this also handles time differently?):

{code:title=oracle_adapter.rb|borderStyle=solid}
...
        def select(sql, name = nil)
          cursor = execute(sql, name)
          cols = cursor.get_col_names.map { |x| oracle_downcase(x) }
          rows = []

          while row = cursor.fetch
            hash = Hash.new

            cols.each_with_index do |col, i|
              hash[col] =
                case row[i]
                when OCI8::LOB
                  name == 'Writable Large Object' ? row[i]: row[i].read
                when OraDate
                  (row[i].hour == 0 and row[i].minute == 0 and row[i].second == 
0) ?
                  row[i].to_date : row[i].to_time
                else row[i]
                end unless col == 'raw_rnum_'
            end

            rows << hash
          end

          rows
        ensure
          cursor.close if cursor
        end
...
{code}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://jira.codehaus.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe from this list please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to