Created
March 25, 2011 11:14
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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