Skip to content

Instantly share code, notes, and snippets.

@nicobrevin
Created March 25, 2011 11:14
Show Gist options
  • Save nicobrevin/886697 to your computer and use it in GitHub Desktop.
Save nicobrevin/886697 to your computer and use it in GitHub Desktop.
Java implementation of process_result_set for improving performance of creating row hashes from a ResultSet
package com.msp;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyHash;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.RubySymbol;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
public class DatasetUtils {
private static IRubyObject BIG_DECIMAL = null;
private static RubyModule LAZY_DATE = null;
/**
* Run this method only once during init to add the method in
* @param runtime
*/
public static void patchModule(RubyModule module) {
BIG_DECIMAL = module.getRuntime().getClass("BigDecimal");
LAZY_DATE = module.getRuntime().getClassFromPath("MSP::LazyDate");
module.defineAnnotatedMethods(DatasetUtils.class);
}
/**
* Attempt at speeding up the conversion process from a JDBC result set in to
* a Sequel row
*/
@JRubyMethod(name="process_result_set", required = 1)
public static void processResultSet(ThreadContext context, IRubyObject recv, IRubyObject r_rs, Block block) throws SQLException {
Ruby runtime = context.getRuntime();
try {
ResultSet rs = (ResultSet) r_rs.toJava(ResultSet.class);
ResultSetMetaData md = rs.getMetaData();
int cc = md.getColumnCount();
IRubyObject[] labels = new RubySymbol[cc];
for (int i = 0; i < cc; i++) {
String label = md.getColumnLabel(i + 1);
labels[i] = recv.callMethod(context, "output_identifier", JavaEmbedUtils.javaToRuby(runtime, label));
}
// Adapters have to set this as sequel uses it to get schema information about tables
recv.getInstanceVariables().setInstanceVariable("@columns",
RubyArray.newArrayNoCopyLight(runtime, labels));
while (rs.next()) {
// populate the hash
RubyHash hash = new RubyHash(runtime);
for (int i = 0; i < cc; i++) {
Object obj = rs.getObject(i + 1);
if (obj instanceof java.sql.Date || obj instanceof Timestamp || obj instanceof Time) {
obj = LAZY_DATE.callMethod(context, "new", JavaEmbedUtils.javaToRuby(runtime, obj));
} else if (obj instanceof BigDecimal) {
obj = BIG_DECIMAL.callMethod(context, "new", RubyString.newUnicodeString(runtime, obj.toString()));
} else {
obj = JavaEmbedUtils.javaToRuby(runtime, obj);
}
// FIXME - support more types, see sequel/dataset/jdbc - convert_type
hash.put(labels[i], obj);
}
// pass the hash to our block
block.call(context, new IRubyObject[] {hash});
}
} catch (SQLException e) {
throw RaiseException.createNativeRaiseException(runtime, e);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment