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();
+ }
}