Title: [767] trunk/activerecord-jdbc: Improve performance of adapters by implementing recognizers in Java, instead of doing a really bad-performing regexp
Revision
767
Author
olabini
Date
2007-10-16 07:34:34 -0400 (Tue, 16 Oct 2007)

Log Message

Improve performance of adapters by implementing recognizers in Java, instead of doing a really bad-performing regexp

Modified Paths

Diff

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


--- trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2007-10-16 08:02:27 UTC (rev 766)
+++ trunk/activerecord-jdbc/lib/active_record/connection_adapters/jdbc_adapter.rb	2007-10-16 11:34:34 UTC (rev 767)
@@ -352,6 +352,14 @@
         metadata.close rescue nil
       end
 
+#      def self.insert?(sql)
+#        /\A\s*insert/i =~ sql
+#      end
+      
+#      def self.select?(sql)
+#        /\A\s*\(?\s*(select|show)/i =~ sql
+#      end
+
       private
       def configure_jndi
         jndi = @config[:jndi].to_s
@@ -483,16 +491,16 @@
           _execute(sql,name)
         end
       end
-
+      
+      
       # we need to do it this way, to allow Rails stupid tests to always work
       # even if we define a new execute method. Instead of mixing in a new
       # execute, an _execute should be mixed in.
       def _execute(sql, name = nil)
-        case sql.strip
-        when /\Ainsert/i:
-            @connection.execute_insert(sql)
-        when /\A\(?\s*(select|show)/i:
-            @connection.execute_query(sql)
+        if JdbcConnection::select?(sql)
+          @connection.execute_query(sql)
+        elsif JdbcConnection::insert?(sql)
+          @connection.execute_insert(sql)
         else
           @connection.execute_update(sql)
         end

Modified: trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java (766 => 767)


--- trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java	2007-10-16 08:02:27 UTC (rev 766)
+++ trunk/activerecord-jdbc/src/java/JdbcAdapterInternalService.java	2007-10-16 11:34:34 UTC (rev 767)
@@ -101,6 +101,9 @@
 
         cJdbcConn.defineFastMethod("write_large_object",cf.getFastOptSingletonMethod("write_large_object"));
 
+        cJdbcConn.getMetaClass().defineFastMethod("insert?",cf.getFastSingletonMethod("insert_p", IRubyObject.class));
+        cJdbcConn.getMetaClass().defineFastMethod("select?",cf.getFastSingletonMethod("select_p", IRubyObject.class));
+
         RubyModule jdbcSpec = runtime.getOrCreateModule("JdbcSpec");
         JDBCMySQLSpec.load(runtime, jdbcSpec);
         JDBCDerbySpec.load(runtime, jdbcSpec);
@@ -108,6 +111,115 @@
         return true;
     }
 
+    private static int whitespace(int p, final int pend, ByteList bl) {
+        while(p < pend) {
+            switch(bl.bytes[p]) {
+            case ' ':
+            case '\n':
+            case '\r':
+            case '\t':
+                p++;
+                break;
+            default:
+                return p;
+            }
+        }
+        return p;
+    }
+
+    public static IRubyObject insert_p(IRubyObject recv, IRubyObject _sql) {
+        ByteList bl = _sql.convertToString().getByteList();
+
+        int p = bl.begin;
+        int pend = p + bl.realSize;
+
+        p = whitespace(p, pend, bl);
+
+        if(pend - p >= 6) {
+            switch(bl.bytes[p++]) {
+            case 'i':
+            case 'I':
+                switch(bl.bytes[p++]) {
+                case 'n':
+                case 'N':
+                    switch(bl.bytes[p++]) {
+                    case 's':
+                    case 'S':
+                        switch(bl.bytes[p++]) {
+                        case 'e':
+                        case 'E':
+                            switch(bl.bytes[p++]) {
+                            case 'r':
+                            case 'R':
+                                switch(bl.bytes[p++]) {
+                                case 't':
+                                case 'T':
+                                    return recv.getRuntime().getTrue();
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return recv.getRuntime().getFalse();
+    }
+
+    public static IRubyObject select_p(IRubyObject recv, IRubyObject _sql) {
+        ByteList bl = _sql.convertToString().getByteList();
+
+        int p = bl.begin;
+        int pend = p + bl.realSize;
+
+        p = whitespace(p, pend, bl);
+
+        if(pend - p >= 6) {
+            if(bl.bytes[p] == '(') {
+                p++;
+                p = whitespace(p, pend, bl);
+            }
+            if(pend - p >= 6) {
+                switch(bl.bytes[p++]) {
+                case 's':
+                case 'S':
+                    switch(bl.bytes[p++]) {
+                    case 'e':
+                    case 'E':
+                        switch(bl.bytes[p++]) {
+                        case 'l':
+                        case 'L':
+                            switch(bl.bytes[p++]) {
+                            case 'e':
+                            case 'E':
+                                switch(bl.bytes[p++]) {
+                                case 'c':
+                                case 'C':
+                                    switch(bl.bytes[p++]) {
+                                    case 't':
+                                    case 'T':
+                                        return recv.getRuntime().getTrue();
+                                    }
+                                }
+                            }
+                        }
+                    case 'h':
+                    case 'H':
+                        switch(bl.bytes[p++]) {
+                        case 'o':
+                        case 'O':
+                            switch(bl.bytes[p++]) {
+                            case 'w':
+                            case 'W':
+                                return recv.getRuntime().getTrue();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return recv.getRuntime().getFalse();
+    }
+
     private static ResultSet intoResultSet(IRubyObject inp) {
         return (ResultSet)((inp instanceof JavaObject ? ((JavaObject)inp) : (((JavaObject)(inp.getInstanceVariable("@java_object"))))).getValue());
     }   
_______________________________________________
Jruby-extras-devel mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/jruby-extras-devel

Reply via email to