[ruby-oci8-commit] [492] trunk/ruby-oci8: enable statement caching per session in OCI layer if the Oracle client is 9iR2 or upper .

nobody at rubyforge.org nobody at rubyforge.org
Thu Jan 19 08:42:26 EST 2012


Revision: 492
Author:   kubo
Date:     2012-01-19 08:42:25 -0500 (Thu, 19 Jan 2012)

Log Message:
-----------
enable statement caching per session in OCI layer if the Oracle client is 9iR2 or upper.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/apiwrap.yml
    trunk/ruby-oci8/ext/oci8/stmt.c
    trunk/ruby-oci8/lib/oci8/oci8.rb
    trunk/ruby-oci8/lib/oci8/properties.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2012-01-19 11:56:19 UTC (rev 491)
+++ trunk/ruby-oci8/ChangeLog	2012-01-19 13:42:25 UTC (rev 492)
@@ -1,4 +1,9 @@
 2012-01-19  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/apiwrap.yml, ext/oci8/stmt.c, lib/oci8/oci8.rb,
+	  lib/oci8/properties.rb: enable statement caching per session in OCI layer
+	    if the Oracle client is 9iR2 or upper.
+
+2012-01-19  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/apiwrap.yml, ext/oci8/oci8.c, lib/oci8/oci8.rb: replace
 	    OCILogon() with OCILogon2() and use the latter to use
 	    ConnectionPool.

Modified: trunk/ruby-oci8/ext/oci8/apiwrap.yml
===================================================================
--- trunk/ruby-oci8/ext/oci8/apiwrap.yml	2012-01-19 11:56:19 UTC (rev 491)
+++ trunk/ruby-oci8/ext/oci8/apiwrap.yml	2012-01-19 13:42:25 UTC (rev 492)
@@ -1343,6 +1343,28 @@
             - dvoid *envhp
             - const oratext *name
 
+OCIStmtPrepare2:
+  :version: 920
+  :args:
+            - OCISvcCtx *svchp
+            - OCIStmt **stmtp
+            - OCIError *errhp
+            - const OraText *stmt
+            - ub4 stmt_len
+            - const OraText *key
+            - ub4 key_len
+            - ub4 language
+            - ub4 mode
+
+OCIStmtRelease:
+  :version: 920
+  :args:
+            - OCIStmt *stmtp
+            - OCIError *errhp
+            - const OraText *key
+            - ub4 key_len
+            - ub4 mode
+
 #
 # Oracle 10.1
 #

Modified: trunk/ruby-oci8/ext/oci8/stmt.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/stmt.c	2012-01-19 11:56:19 UTC (rev 491)
+++ trunk/ruby-oci8/ext/oci8/stmt.c	2012-01-19 13:42:25 UTC (rev 492)
@@ -35,6 +35,7 @@
     VALUE svc;
     VALUE binds;
     VALUE defns;
+    int use_stmt_release;
 } oci8_stmt_t;
 
 static void oci8_stmt_mark(oci8_base_t *base)
@@ -51,6 +52,11 @@
     stmt->svc = Qnil;
     stmt->binds = Qnil;
     stmt->defns = Qnil;
+    if (stmt->use_stmt_release) {
+        OCIStmtRelease(base->hp.stmt, oci8_errhp, NULL, 0, OCI_DEFAULT);
+        base->type = 0;
+        stmt->use_stmt_release = 0;
+    }
 }
 
 static oci8_base_vtable_t oci8_stmt_vtable = {
@@ -62,20 +68,38 @@
 static VALUE oci8_stmt_initialize(int argc, VALUE *argv, VALUE self)
 {
     oci8_stmt_t *stmt = DATA_PTR(self);
+    oci8_svcctx_t *svcctx;
     VALUE svc;
     VALUE sql;
     sword rv;
 
     rb_scan_args(argc, argv, "11", &svc, &sql);
 
-    oci8_check_pid_consistency(oci8_get_svcctx(svc));
-    if (argc > 1)
+    svcctx = oci8_get_svcctx(svc);
+    oci8_check_pid_consistency(svcctx);
+    if (argc > 1 && oracle_client_version >= ORAVER_9_2) {
         OCI8SafeStringValue(sql);
 
-    rv = OCIHandleAlloc(oci8_envhp, &stmt->base.hp.ptr, OCI_HTYPE_STMT, 0, NULL);
-    if (rv != OCI_SUCCESS)
-        oci8_env_raise(oci8_envhp, rv);
-    stmt->base.type = OCI_HTYPE_STMT;
+        rv = OCIStmtPrepare2(svcctx->base.hp.svc, &stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT);
+        if (IS_OCI_ERROR(rv)) {
+            chker2(rv, &svcctx->base);
+        }
+        stmt->base.type = OCI_HTYPE_STMT;
+        stmt->use_stmt_release = 1;
+    } else {
+        rv = OCIHandleAlloc(oci8_envhp, &stmt->base.hp.ptr, OCI_HTYPE_STMT, 0, NULL);
+        if (rv != OCI_SUCCESS) {
+            oci8_env_raise(oci8_envhp, rv);
+        }
+        stmt->base.type = OCI_HTYPE_STMT;
+        if (argc > 1) {
+            OCI8SafeStringValue(sql);
+            rv = OCIStmtPrepare(stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
+            if (IS_OCI_ERROR(rv)) {
+                chker3(rv, &svcctx->base, stmt->base.hp.stmt);
+            }
+        }
+    }
     stmt->svc = svc;
     stmt->binds = rb_hash_new();
     stmt->defns = rb_ary_new();
@@ -84,12 +108,6 @@
     rb_ivar_set(stmt->base.self, id_at_con, svc);
     rb_ivar_set(stmt->base.self, id_at_max_array_size, Qnil);
 
-    if (argc > 1) {
-        rv = OCIStmtPrepare(stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), OCI_NTV_SYNTAX, OCI_DEFAULT);
-        if (IS_OCI_ERROR(rv)) {
-            chker3(rv, &stmt->base, stmt->base.hp.stmt);
-        }
-    }
     oci8_link_to_parent((oci8_base_t*)stmt, (oci8_base_t*)DATA_PTR(svc));
     return Qnil;
 }

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2012-01-19 11:56:19 UTC (rev 491)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2012-01-19 13:42:25 UTC (rev 492)
@@ -118,6 +118,8 @@
       raise "unknown privilege type #{mode}"
     end
 
+    stmt_cache_size = OCI8.properties[:statement_cache_size]
+
     if mode.nil? and cred.nil?
       # logon by the OCI function OCILogon2().
       logon2_mode = 0
@@ -126,7 +128,17 @@
         dbname = dbname.send(:pool_name)
         logon2_mode |= 0x0200 # OCI_LOGON2_CPOOL
       end
+      if stmt_cache_size
+        # enable statement caching
+        logon2_mode |= 0x0004 # OCI_LOGON2_STMTCACHE
+      end
+
       logon2(username, password, dbname, logon2_mode)
+
+      if stmt_cache_size
+        # set statement cache size
+        attr_set_ub4(176, stmt_cache_size) # 176: OCI_ATTR_STMTCACHESIZE
+      end
     else
       # logon by the OCI function OCISessionBegin().
       attach_mode = 0
@@ -135,12 +147,21 @@
         dbname = dbname.send(:pool_name)
         attach_mode |= 0x0200 # OCI_CPOOL
       end
+      if stmt_cache_size
+        # enable statement caching
+        attach_mode |= 0x0004 # OCI_STMT_CACHE
+      end
 
       allocate_handles()
       session_handle.send(:attr_set_string, OCI_ATTR_USERNAME, username) if username
       session_handle.send(:attr_set_string, OCI_ATTR_PASSWORD, password) if password
       server_attach(dbname, attach_mode)
       session_begin(cred ? cred : OCI_CRED_RDBMS, mode ? mode : OCI_DEFAULT)
+
+      if stmt_cache_size
+        # set statement cache size
+        attr_set_ub4(176, stmt_cache_size) # 176: OCI_ATTR_STMTCACHESIZE
+      end
     end
 
     @prefetch_rows = nil

Modified: trunk/ruby-oci8/lib/oci8/properties.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/properties.rb	2012-01-19 11:56:19 UTC (rev 491)
+++ trunk/ruby-oci8/lib/oci8/properties.rb	2012-01-19 13:42:25 UTC (rev 492)
@@ -8,8 +8,13 @@
     :length_semantics => :byte,
     :bind_string_as_nchar => false,
     :float_conversion_type => :ruby,
+    :statement_cache_size => 20,
   }
 
+  if OCI8.oracle_client_version < OCI8::ORAVER_9_2
+    @@properties[:statement_cache_size] = nil
+  end
+
   def @@properties.[](name)
     raise IndexError, "No such property name: #{name}" unless @@properties.has_key?(name)
     super(name)
@@ -27,6 +32,12 @@
     when :float_conversion_type
       # handled by native code in oci8lib_xx.so.
       OCI8.__set_property(name, val)
+    when :statement_cache_size
+      if OCI8.oracle_client_version < OCI8::ORAVER_9_2
+        raise RuntimeError, ":statement_cache_size is disabled on Oracle 9iR1 client."
+      end
+      val = val.to_i
+      raise ArgumentError, "The property value for :statement_cache_size must not be negative." if val < 0
     end
     super(name, val)
   end
@@ -74,6 +85,13 @@
   #     15.700000000000001 by Float#to_s.
   #     See: http://rubyforge.org/forum/forum.php?thread_id=50030&forum_id=1078
   #
+  # [:statement_cache_size]
+  #     (new in 2.1.1)
+  #     
+  #     The statement cache size per each session. The default value is 20 statements.
+  #     This feature is available on Oracle 9iR2 or later.
+  #     See: http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci09adv.htm#i471377
+  #
   def self.properties
     @@properties
   end




More information about the ruby-oci8-commit mailing list