Title: [672] trunk/activerecord-jdbc: Make Oracle support writing of BLOB's correctly.
Revision
672
Author
olabini
Date
2007-07-20 09:47:51 -0400 (Fri, 20 Jul 2007)

Log Message

Make Oracle support writing of BLOB's correctly. JRUBY-1223.

Modified Paths


Diff

Modified: trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb (671 => 672)


--- trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2007-07-20 13:15:48 UTC (rev 671)
+++ trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2007-07-20 13:47:51 UTC (rev 672)
@@ -489,6 +489,10 @@
       def rollback_db_transaction
         @connection.rollback
       end
+      
+      def write_large_object(*args)
+        @connection.write_large_object(*args)
+      end
 
       private
       def select(sql, name=nil)

Modified: trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_oracle.rb (671 => 672)


--- trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_oracle.rb	2007-07-20 13:15:48 UTC (rev 671)
+++ trunk/activerecord-jdbc/lib/jdbc_adapter/jdbc_oracle.rb	2007-07-20 13:47:51 UTC (rev 672)
@@ -1,3 +1,23 @@
+module ::ActiveRecord
+  class Base
+    # After setting large objects to empty, write data back with a helper method
+    after_save :write_lobs
+    def write_lobs() #:nodoc:
+      if connection.is_a?(JdbcSpec::Oracle)
+        self.class.columns.select { |c| c.sql_type =~ /LOB\(|LOB$/i }.each { |c|
+          value = self[c.name]
+          value = value.to_yaml if unserializable_attribute?(c.name, c)
+          next if value.nil?  || (value == '')
+
+          connection.write_large_object(c.type == :binary, c.name, self.class.table_name, self.class.primary_key, quote_value(id), value)
+        }
+      end
+    end
+
+    private :write_lobs
+  end
+end
+
 module ::JdbcSpec
   module ActiveRecordExtensions
     def oracle_connection(config)

Modified: trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java (671 => 672)


--- trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java	2007-07-20 13:15:48 UTC (rev 671)
+++ trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java	2007-07-20 13:47:51 UTC (rev 672)
@@ -28,6 +28,8 @@
 import java.io.IOException;
 import java.io.Reader;
 import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.io.StringReader;
 
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
@@ -96,6 +98,8 @@
         cJdbcConn.defineFastMethod("insert_bind",cf.getFastOptSingletonMethod("insert_bind"));
         cJdbcConn.defineFastMethod("update_bind",cf.getFastOptSingletonMethod("update_bind"));
 
+        cJdbcConn.defineFastMethod("write_large_object",cf.getFastOptSingletonMethod("write_large_object"));
+
         RubyModule jdbcSpec = runtime.getOrCreateModule("JdbcSpec");
         JDBCMySQLSpec.load(runtime, jdbcSpec);
         JDBCDerbySpec.load(runtime, jdbcSpec);
@@ -752,4 +756,34 @@
         }
         return runtime.getNil();
     }
+
+
+    private final static String LOB_UPDATE = "UPDATE ? WHERE ";
+
+    /*
+     * (is binary?, colname, tablename, primary key, id, value)
+     */
+    public static IRubyObject write_large_object(IRubyObject recv, IRubyObject[] args) throws SQLException, IOException {
+        Ruby runtime = recv.getRuntime();
+        Arity.checkArgumentCount(runtime, args, 6, 6);
+        Connection c = (Connection)recv.dataGetStruct();
+        String sql = "UPDATE " + args[2].toString() + " SET " + args[1].toString() + " = ? WHERE " + args[3] + "=" + args[4];
+        PreparedStatement ps = null;
+        try {
+            ByteList outp = RubyString.objAsString(args[5]).getByteList();
+            ps = c.prepareStatement(sql);
+            if(args[0].isTrue()) { // binary
+                ps.setBinaryStream(1,new ByteArrayInputStream(outp.bytes, outp.begin, outp.realSize), outp.realSize);
+            } else { // clob
+                String ss = outp.toString();
+                ps.setCharacterStream(1,new StringReader(ss), ss.length());
+            }
+            ps.executeUpdate();
+        } finally {
+            try {
+                ps.close();
+            } catch(Exception e) {}
+        }
+        return runtime.getNil();
+    }
 }
_______________________________________________
Jruby-extras-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/jruby-extras-devel

Reply via email to