[ruby-oci8-commit] [393] trunk/ruby-oci8: * ext/oci8/bind.c: fix a bug that a string is bound to RAW,

nobody at rubyforge.org nobody at rubyforge.org
Tue May 4 08:59:37 EDT 2010


Revision: 393
Author:   kubo
Date:     2010-05-04 08:59:37 -0400 (Tue, 04 May 2010)

Log Message:
-----------
* ext/oci8/bind.c: fix a bug that a string is bound to RAW,
    its encoding was convertd to OCI.encoding.
* ext/oci8/encoding.c: delete an unused strcuture.
* ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/ocihandle.c,
    lib/oci8/oci8.rb: do refactering to make it easy to
    implement new authentication features.
* lib/oci8.rb.in, lib/oci8/metadata.rb, lib/oci8/ocihandle.rb:
    move constant definitions from metadata.rb to ocihandle.rb.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/bind.c
    trunk/ruby-oci8/ext/oci8/encoding.c
    trunk/ruby-oci8/ext/oci8/oci8.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/ocihandle.c
    trunk/ruby-oci8/lib/oci8/metadata.rb
    trunk/ruby-oci8/lib/oci8/oci8.rb
    trunk/ruby-oci8/lib/oci8.rb.in

Added Paths:
-----------
    trunk/ruby-oci8/lib/oci8/ocihandle.rb

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ChangeLog	2010-05-04 12:59:37 UTC (rev 393)
@@ -1,3 +1,13 @@
+2010-05-04  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/bind.c: fix a bug that a string is bound to RAW,
+	    its encoding was convertd to OCI.encoding.
+	* ext/oci8/encoding.c: delete an unused strcuture.
+	* ext/oci8/oci8.c, ext/oci8/oci8.h, ext/oci8/ocihandle.c,
+	    lib/oci8/oci8.rb: do refactering to make it easy to
+	    implement new authentication features.
+	* lib/oci8.rb.in, lib/oci8/metadata.rb, lib/oci8/ocihandle.rb:
+	    move constant definitions from metadata.rb to ocihandle.rb.
+
 2010-05-03  KUBO Takehiro  <kubo at jiubao.org>
 	* ext/oci8/bind.c, ext/oci8/oci8.h, lib/oci8/bindtype.rb:
 	    change the length semantics from byte to char for string

Modified: trunk/ruby-oci8/ext/oci8/bind.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/bind.c	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ext/oci8/bind.c	2010-05-04 12:59:37 UTC (rev 393)
@@ -2,9 +2,6 @@
 /*
  * bind.c
  *
- * $Author$
- * $Date$
- *
  * Copyright (C) 2002-2010 KUBO Takehiro <kubo at jiubao.org>
  */
 #include "oci8.h"
@@ -118,6 +115,19 @@
     return rb_str_new(vstr->buf, vstr->size);
 }
 
+static void bind_raw_set(oci8_bind_t *obind, void *data, void **null_structp, VALUE val)
+{
+    oci8_bind_string_t *obs = (oci8_bind_string_t *)obind;
+    oci8_vstr_t *vstr = (oci8_vstr_t *)data;
+
+    StringValue(val);
+    if (RSTRING_LEN(val) > obs->bytelen) {
+        rb_raise(rb_eArgError, "too long String to set. (%ld for %d)", RSTRING_LEN(val), obs->bytelen);
+    }
+    memcpy(vstr->buf, RSTRING_PTR(val), RSTRING_LEN(val));
+    vstr->size = RSTRING_LEN(val);
+}
+
 static const oci8_bind_class_t bind_raw_class = {
     {
         NULL,
@@ -125,7 +135,7 @@
         sizeof(oci8_bind_string_t)
     },
     bind_raw_get,
-    bind_string_set,
+    bind_raw_set,
     bind_string_init,
     NULL,
     NULL,

Modified: trunk/ruby-oci8/ext/oci8/encoding.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/encoding.c	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ext/oci8/encoding.c	2010-05-04 12:59:37 UTC (rev 393)
@@ -11,16 +11,6 @@
 #define OCI_NLS_MAXBUFSZ 100
 #endif
 
-/* type of callback function's argument */
-typedef struct {
-    oci8_svcctx_t *svcctx;
-    OCIStmt *stmtp;
-    union {
-        VALUE name;
-        int csid;
-    } u;
-} cb_arg_t;
-
 /* NLS ratio, maximum number of bytes per one chracter */
 int oci8_nls_ratio = 1;
 

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2010-05-04 12:59:37 UTC (rev 393)
@@ -2,7 +2,7 @@
 /*
  * oci8.c - part of ruby-oci8
  *
- * Copyright (C) 2002-2009 KUBO Takehiro <kubo at jiubao.org>
+ * Copyright (C) 2002-2010 KUBO Takehiro <kubo at jiubao.org>
  *
  */
 #include "oci8.h"
@@ -30,33 +30,63 @@
 #define OCI_ATTR_CLIENT_INFO 368
 #endif
 
+#define OCI8_STATE_SESSION_BEGIN_WAS_CALLED 0x01
+#define OCI8_STATE_SERVER_ATTACH_WAS_CALLED 0x02
+
 static VALUE cOCI8;
 
+static void oci8_svcctx_mark(oci8_base_t *base)
+{
+    oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
+
+    if (svcctx->session) {
+        rb_gc_mark(svcctx->session->self);
+    }
+    if (svcctx->server) {
+        rb_gc_mark(svcctx->server->self);
+    }
+}
+
 static void oci8_svcctx_free(oci8_base_t *base)
 {
     oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
 
-    if (svcctx->authhp) {
-        OCIHandleFree(svcctx->authhp, OCI_HTYPE_SESSION);
-        svcctx->authhp = NULL;
+    if (svcctx->session) {
+        oci8_base_free(svcctx->session);
+        svcctx->session = NULL;
     }
-    if (svcctx->srvhp) {
-        OCIHandleFree(svcctx->srvhp, OCI_HTYPE_SERVER);
-        svcctx->srvhp = NULL;
+    if (svcctx->server) {
+        oci8_base_free(svcctx->server);
+        svcctx->server = NULL;
     }
 }
 
+static void oci8_svcctx_init(oci8_base_t *base)
+{
+    oci8_svcctx_t *svcctx = (oci8_svcctx_t *)base;
+
+    svcctx->executing_thread = Qnil;
+    svcctx->session = DATA_PTR(rb_obj_alloc(oci8_cOCIHandle));
+    svcctx->server = DATA_PTR(rb_obj_alloc(oci8_cOCIHandle));
+    svcctx->pid = getpid();
+    svcctx->is_autocommit = 0;
+#ifdef RUBY_VM
+    svcctx->non_blocking = 1;
+#endif
+    svcctx->long_read_len = INT2FIX(65535);
+}
+
 static oci8_base_class_t oci8_svcctx_class = {
-    NULL,
+    oci8_svcctx_mark,
     oci8_svcctx_free,
-    sizeof(oci8_svcctx_t)
+    sizeof(oci8_svcctx_t),
+    oci8_svcctx_init,
 };
 
 static VALUE oracle_client_vernum; /* Oracle client version number */
 static VALUE sym_SYSDBA;
 static VALUE sym_SYSOPER;
 static ID id_at_prefetch_rows;
-static ID id_at_username;
 static ID id_set_prefetch_rows;
 
 static VALUE oci8_s_oracle_client_vernum(VALUE klass)
@@ -143,184 +173,206 @@
     return rb_ary_new3(4, user, pass, dbname, mode);
 }
 
+static void call_oci_logoff(oci8_svcctx_t *svcctx)
+{
+    svcctx->logoff_method = NULL;
+    svcctx->session->type = 0;
+    svcctx->server->type = 0;
+    oci_lc(OCILogoff_nb(svcctx, svcctx->base.hp.svc, oci8_errhp));
+    svcctx->base.type = 0;
+}
+
+static void call_session_end(oci8_svcctx_t *svcctx)
+{
+    sword rv = OCI_SUCCESS;
+
+    if (svcctx->state & OCI8_STATE_SESSION_BEGIN_WAS_CALLED) {
+        rv = OCISessionEnd_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, svcctx->session->hp.authhp, OCI_DEFAULT);
+        svcctx->state &= ~OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
+    }
+    if (svcctx->state & OCI8_STATE_SERVER_ATTACH_WAS_CALLED) {
+        rv = OCIServerDetach_nb(svcctx, svcctx->server->hp.srvhp, oci8_errhp, OCI_DEFAULT);
+        svcctx->state &= ~OCI8_STATE_SERVER_ATTACH_WAS_CALLED;
+    }
+    svcctx->logoff_method = NULL;
+    if (rv != OCI_SUCCESS) {
+        oci8_raise(oci8_errhp, rv, NULL);
+    }
+}
+
 /*
  * call-seq:
- *   new(username, password, dbname = nil, privilege = nil)
+ *   logon(username, password, dbname) -> connection
  *
- * Connects to an Oracle database server by +username+ and +password+
- * at +dbname+ as +privilege+.
+ * <b>internal use only</b>
  *
- * === connecting to the local server
+ * Creates a simple logon session by the OCI function OCILogon().
+ */
+static VALUE oci8_logon(VALUE self, VALUE username, VALUE password, VALUE dbname)
+{
+    oci8_svcctx_t *svcctx = DATA_PTR(self);
+
+    if (svcctx->logoff_method != NULL) {
+        rb_raise(rb_eRuntimeError, "Could not reuse the session.");
+    }
+
+    /* check arugmnets */
+    OCI8SafeStringValue(username);
+    OCI8SafeStringValue(password);
+    if (!NIL_P(dbname)) {
+        OCI8SafeStringValue(dbname);
+    }
+
+    /* logon */
+    oci_lc(OCILogon_nb(svcctx, oci8_envhp, oci8_errhp, &svcctx->base.hp.svc,
+                       RSTRING_ORATEXT(username), RSTRING_LEN(username),
+                       RSTRING_ORATEXT(password), RSTRING_LEN(password),
+                       NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
+                       NIL_P(dbname) ? 0 : RSTRING_LEN(dbname)));
+    svcctx->base.type = OCI_HTYPE_SVCCTX;
+    svcctx->logoff_method = call_oci_logoff;
+    return Qnil;
+}
+
+/*
+ * call-seq:
+ *   allocate_handles()
  *
- * Set +username+ and +password+ or pass "username/password" as a
- * single argument.
+ * <b>internal use only</b>
  *
- *   OCI8.new('scott', 'tiger')
- * or
- *   OCI8.new('scott/tiger')
+ * Allocates a service context handle, a session handle and a
+ * server handle to use explicit attach and begin-session calls.
+ */
+static VALUE oci8_allocate_handles(VALUE self)
+{
+    oci8_svcctx_t *svcctx = DATA_PTR(self);
+    sword rv;
+
+    if (svcctx->logoff_method != NULL) {
+        rb_raise(rb_eRuntimeError, "Could not reuse the session.");
+    }
+    svcctx->logoff_method = call_session_end;
+    svcctx->state = 0;
+
+    /* allocate a service context handle */
+    rv = OCIHandleAlloc(oci8_envhp, &svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, 0, 0);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(oci8_envhp, rv);
+    svcctx->base.type = OCI_HTYPE_SVCCTX;
+
+    /* alocalte a session handle */
+    rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->session->hp.ptr, OCI_HTYPE_SESSION, 0, 0);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(oci8_envhp, rv);
+    svcctx->session->type = OCI_HTYPE_SESSION;
+
+    /* alocalte a server handle */
+    rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->server->hp.ptr, OCI_HTYPE_SERVER, 0, 0);
+    if (rv != OCI_SUCCESS)
+        oci8_env_raise(oci8_envhp, rv);
+    svcctx->server->type = OCI_HTYPE_SERVER;
+    return self;
+}
+
+/*
+ * call-seq:
+ *   session_handle -> a session handle
  *
- * === connecting to a remote server
+ * <b>internal use only</b>
  *
- * Set +username+, +password+ and +dbname+ or pass
- * "username/password at dbname" as a single argument.
+ * Returns a session handle associated with the service context handle.
+ */
+static VALUE oci8_get_session_handle(VALUE self)
+{
+    oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
+    return svcctx->session->self;
+}
+
+/*
+ * call-seq:
+ *   server_handle -> a server handle
  *
- *   OCI8.new('scott', 'tiger', 'orcl.world')
- * or
- *   OCI8.new('scott/tiger at orcl.world')
+ * <b>internal use only</b>
  *
- * The +dbname+ is a net service name or an easy connectection
- * identifier. The former is a name listed in the file tnsnames.ora.
- * Ask to your DBA if you don't know what it is. The latter has the
- * syntax as "//host:port/service_name".
+ * Returns a server handle associated with the service context handle.
+ */
+static VALUE oci8_get_server_handle(VALUE self)
+{
+    oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
+    return svcctx->server->self;
+}
+
+/*
+ * call-seq:
+ *   server_attach(dbname, mode)
  *
- *   OCI8.new('scott', 'tiger', '//remote-host:1521/XE')
- * or
- *   OCI8.new('scott/tiger@//remote-host:1521/XE')
+ * <b>internal use only</b>
  *
- * === connecting as a privileged user
+ * Attachs to the server by the OCI function OCIServerAttach().
+ */
+static VALUE oci8_server_attach(VALUE self, VALUE dbname, VALUE mode)
+{
+    oci8_svcctx_t *svcctx = oci8_get_svcctx(self);
+
+    if (svcctx->logoff_method != call_session_end) {
+        rb_raise(rb_eRuntimeError, "Use this method only for the service context handle created by OCI8#server_handle().");
+    }
+    if (svcctx->state & OCI8_STATE_SERVER_ATTACH_WAS_CALLED) {
+        rb_raise(rb_eRuntimeError, "Could not use this method twice.");
+    }
+
+    /* check arguments */
+    if (!NIL_P(dbname)) {
+        OCI8SafeStringValue(dbname);
+    }
+    Check_Type(mode, T_FIXNUM);
+
+    /* attach to the server */
+    oci_lc(OCIServerAttach_nb(svcctx, svcctx->server->hp.srvhp, oci8_errhp,
+                              NIL_P(dbname) ? NULL : RSTRING_ORATEXT(dbname),
+                              NIL_P(dbname) ? 0 : RSTRING_LEN(dbname),
+                              FIX2UINT(mode)));
+    oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX,
+                      svcctx->server->hp.srvhp, 0, OCI_ATTR_SERVER,
+                      oci8_errhp));
+    svcctx->state |= OCI8_STATE_SERVER_ATTACH_WAS_CALLED;
+    return self;
+}
+
+/*
+ * call-seq:
+ *   session_begin(cred, mode)
  *
- * Set :SYSDBA or :SYSOPER to +privilege+, otherwise
- * "username/password as sysdba" or "username/password as sysoper"
- * as a single argument.
+ * <b>internal use only</b>
  *
- *   OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
- * or
- *   OCI8.new('sys/change_on_install as sysdba')
- *
- * === external OS authentication
- *
- * Set nil to +username+ and +password+, or "/" as a single argument.
- *
- *   OCI8.new(nil, nil)
- * or
- *   OCI8.new('/')
- *
- * To connect to a remote host:
- *
- *   OCI8.new(nil, nil, 'dbname')
- * or
- *   OCI8.new('/@dbname')
- *
- * === proxy authentication
- *
- * Enclose end user's username with square brackets and add it at the
- * end of proxy user's username.
- *
- *   OCI8.new('proxy_user_name[end_user_name]', 'proxy_password')
- * or
- *   OCI8.new('proxy_user_name[end_user_name]/proxy_password')
- *
+ * Begins the session by the OCI function OCISessionBegin().
  */
-static VALUE oci8_svcctx_initialize(int argc, VALUE *argv, VALUE self)
+static VALUE oci8_session_begin(VALUE self, VALUE cred, VALUE mode)
 {
-    VALUE vusername;
-    VALUE vpassword;
-    VALUE vdbname;
-    VALUE vmode;
     oci8_svcctx_t *svcctx = DATA_PTR(self);
-    sword rv;
-    enum logon_type_t logon_type = T_IMPLICIT;
-    ub4 cred = OCI_CRED_RDBMS;
-    ub4 mode = OCI_DEFAULT;
-    OCISvcCtx *svchp = NULL;
 
-    svcctx->executing_thread = Qnil;
-    if (argc == 1) {
-        oci8_do_parse_connect_string(argv[0], &vusername, &vpassword, &vdbname, &vmode);
-    } else {
-        rb_scan_args(argc, argv, "22", &vusername, &vpassword, &vdbname, &vmode);
+    if (svcctx->logoff_method != call_session_end) {
+        rb_raise(rb_eRuntimeError, "Use this method only for the service context handle created by OCI8#server_handle().");
     }
-
-    rb_ivar_set(self, id_at_prefetch_rows, Qnil);
-    rb_ivar_set(self, id_at_username, Qnil);
-    if (NIL_P(vusername) && NIL_P(vpassword)) {
-        /* external credential */
-        logon_type = T_EXPLICIT;
-        cred = OCI_CRED_EXT;
-    } else {
-        /* RDBMS credential */
-        OCI8SafeStringValue(vusername); /* 1 */
-        OCI8SafeStringValue(vpassword); /* 2 */
+    if (svcctx->state & OCI8_STATE_SESSION_BEGIN_WAS_CALLED) {
+        rb_raise(rb_eRuntimeError, "Could not use this method twice.");
     }
-    if (!NIL_P(vdbname)) {
-        OCI8SafeStringValue(vdbname); /* 3 */
-    }
-    if (!NIL_P(vmode)) { /* 4 */
-        logon_type = T_EXPLICIT;
-        Check_Type(vmode, T_SYMBOL);
-        if (vmode == sym_SYSDBA) {
-            mode = OCI_SYSDBA;
-        } else if (vmode == sym_SYSOPER) {
-            mode = OCI_SYSOPER;
-        } else {
-            rb_raise(rb_eArgError, "invalid privilege name %s (expect :SYSDBA or :SYSOPER)", rb_id2name(SYM2ID(vmode)));
-        }
-    }
-    switch (logon_type) {
-    case T_IMPLICIT:
-        rv = OCILogon_nb(svcctx, oci8_envhp, oci8_errhp, &svchp,
-                         RSTRING_ORATEXT(vusername), RSTRING_LEN(vusername),
-                         RSTRING_ORATEXT(vpassword), RSTRING_LEN(vpassword),
-                         NIL_P(vdbname) ? NULL : RSTRING_ORATEXT(vdbname),
-                         NIL_P(vdbname) ? 0 : RSTRING_LEN(vdbname));
-        svcctx->base.hp.svc = svchp;
-        svcctx->base.type = OCI_HTYPE_SVCCTX;
-        svcctx->logon_type = T_IMPLICIT;
-        if (rv != OCI_SUCCESS) {
-            oci8_raise(oci8_errhp, rv, NULL);
-        }
-        break;
-    case T_EXPLICIT:
-        /* allocate OCI handles. */
-        rv = OCIHandleAlloc(oci8_envhp, &svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-        svcctx->base.type = OCI_HTYPE_SVCCTX;
-        rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->authhp, OCI_HTYPE_SESSION, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
-        rv = OCIHandleAlloc(oci8_envhp, (void*)&svcctx->srvhp, OCI_HTYPE_SERVER, 0, 0);
-        if (rv != OCI_SUCCESS)
-            oci8_env_raise(oci8_envhp, rv);
 
-        /* set username and password to OCISession. */
-        if (cred == OCI_CRED_RDBMS) {
-            oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
-                              RSTRING_PTR(vusername), RSTRING_LEN(vusername),
-                              OCI_ATTR_USERNAME, oci8_errhp));
-            oci_lc(OCIAttrSet(svcctx->authhp, OCI_HTYPE_SESSION,
-                              RSTRING_PTR(vpassword), RSTRING_LEN(vpassword),
-                              OCI_ATTR_PASSWORD, oci8_errhp));
-        }
+    /* check arguments */
+    Check_Type(cred, T_FIXNUM);
+    Check_Type(mode, T_FIXNUM);
 
-        /* attach to server and set to OCISvcCtx. */
-        rv = OCIServerAttach_nb(svcctx, svcctx->srvhp, oci8_errhp,
-                                NIL_P(vdbname) ? NULL : RSTRING_ORATEXT(vdbname),
-                                NIL_P(vdbname) ? 0 : RSTRING_LEN(vdbname), OCI_DEFAULT);
-        if (rv != OCI_SUCCESS)
-            oci8_raise(oci8_errhp, rv, NULL);
-        oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, svcctx->srvhp, 0, OCI_ATTR_SERVER, oci8_errhp));
-
-        /* begin session. */
-        rv = OCISessionBegin_nb(svcctx, svcctx->base.hp.ptr, oci8_errhp, svcctx->authhp, cred, mode);
-        if (rv != OCI_SUCCESS)
-            oci8_raise(oci8_errhp, rv, NULL);
-        oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, svcctx->authhp, 0, OCI_ATTR_SESSION, oci8_errhp));
-        svcctx->logon_type = T_EXPLICIT;
-        break;
-    default:
-        break;
-    }
-    svcctx->pid = getpid();
-    svcctx->is_autocommit = 0;
-#ifdef RUBY_VM
-    svcctx->non_blocking = 1;
-#endif
-    svcctx->long_read_len = INT2FIX(65535);
+    /* begin session */
+    oci_lc(OCISessionBegin_nb(svcctx, svcctx->base.hp.ptr, oci8_errhp,
+                              svcctx->session->hp.authhp, FIX2UINT(cred),
+                              FIX2UINT(mode)));
+    oci_lc(OCIAttrSet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX,
+                      svcctx->session->hp.authhp, 0, OCI_ATTR_SESSION,
+                      oci8_errhp));
+    svcctx->state |= OCI8_STATE_SESSION_BEGIN_WAS_CALLED;
     return Qnil;
 }
 
-
 /*
  * call-seq:
  *   logoff
@@ -331,34 +383,13 @@
 static VALUE oci8_svcctx_logoff(VALUE self)
 {
     oci8_svcctx_t *svcctx = (oci8_svcctx_t *)DATA_PTR(self);
-    sword rv;
 
     while (svcctx->base.children != NULL) {
         oci8_base_free(svcctx->base.children);
     }
-    switch (svcctx->logon_type) {
-    case T_IMPLICIT:
+    if (svcctx->logoff_method != NULL) {
         oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
-        rv = OCILogoff_nb(svcctx, svcctx->base.hp.svc, oci8_errhp);
-        svcctx->base.type = 0;
-        svcctx->logon_type = T_NOT_LOGIN;
-        if (rv != OCI_SUCCESS)
-            oci8_raise(oci8_errhp, rv, NULL);
-        svcctx->authhp = NULL;
-        svcctx->srvhp = NULL;
-        break;
-    case T_EXPLICIT:
-        oci_lc(OCITransRollback_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, OCI_DEFAULT));
-        rv = OCISessionEnd_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, svcctx->authhp, OCI_DEFAULT);
-        if (rv == OCI_SUCCESS) {
-            rv = OCIServerDetach_nb(svcctx, svcctx->srvhp, oci8_errhp, OCI_DEFAULT);
-        }
-        svcctx->logon_type = T_NOT_LOGIN;
-        if (rv != OCI_SUCCESS)
-            oci8_raise(oci8_errhp, rv, NULL);
-        break;
-    case T_NOT_LOGIN:
-        break;
+        svcctx->logoff_method(svcctx);
     }
     return Qtrue;
 }
@@ -941,10 +972,6 @@
 VALUE Init_oci8(void)
 {
 #if 0
-    /*
-     * OCIHandle is the abstract base class for all OCI handles and
-     * descriptors which are opaque data types of Oracle Call Interface.
-     */
     oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
     cOCI8 = rb_define_class("OCI8", oci8_cOCIHandle);
 #endif
@@ -960,7 +987,6 @@
     sym_SYSDBA = ID2SYM(rb_intern("SYSDBA"));
     sym_SYSOPER = ID2SYM(rb_intern("SYSOPER"));
     id_at_prefetch_rows = rb_intern("@prefetch_rows");
-    id_at_username = rb_intern("@username");
     id_set_prefetch_rows = rb_intern("prefetch_rows=");
 
     rb_define_singleton_method_nodoc(cOCI8, "oracle_client_vernum", oci8_s_oracle_client_vernum, 0);
@@ -968,7 +994,12 @@
         rb_define_singleton_method(cOCI8, "error_message", oci8_s_error_message, 1);
     }
     rb_define_private_method(cOCI8, "parse_connect_string", oci8_parse_connect_string, 1);
-    rb_define_method(cOCI8, "initialize", oci8_svcctx_initialize, -1);
+    rb_define_private_method(cOCI8, "logon", oci8_logon, 3);
+    rb_define_private_method(cOCI8, "allocate_handles", oci8_allocate_handles, 0);
+    rb_define_private_method(cOCI8, "session_handle", oci8_get_session_handle, 0);
+    rb_define_private_method(cOCI8, "server_handle", oci8_get_server_handle, 0);
+    rb_define_private_method(cOCI8, "server_attach", oci8_server_attach, 2);
+    rb_define_private_method(cOCI8, "session_begin", oci8_session_begin, 2);
     rb_define_method(cOCI8, "logoff", oci8_svcctx_logoff, 0);
     rb_define_method(cOCI8, "parse", oci8_svcctx_parse, 1);
     rb_define_method(cOCI8, "commit", oci8_commit, 0);
@@ -1010,10 +1041,10 @@
 {
     oci8_svcctx_t *svcctx = oci8_get_svcctx(obj);
 
-    if (svcctx->authhp == NULL) {
-        oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->authhp, 0, OCI_ATTR_SESSION, oci8_errhp));
+    if (svcctx->session->hp.authhp == NULL) {
+        oci_lc(OCIAttrGet(svcctx->base.hp.ptr, OCI_HTYPE_SVCCTX, &svcctx->session->hp.authhp, 0, OCI_ATTR_SESSION, oci8_errhp));
     }
-    return svcctx->authhp;
+    return svcctx->session->hp.authhp;
 }
 
 void oci8_check_pid_consistency(oci8_svcctx_t *svcctx)

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2010-05-04 12:59:37 UTC (rev 393)
@@ -249,6 +249,7 @@
     void (*mark)(oci8_base_t *base);
     void (*free)(oci8_base_t *base);
     size_t size;
+    void (*init)(oci8_base_t *base);
 };
 
 struct oci8_bind_class {
@@ -269,6 +270,8 @@
     union {
         dvoid *ptr;
         OCISvcCtx *svc;
+        OCIServer *srvhp;
+        OCISession *authhp;
         OCIStmt *stmt;
         OCIDefine *dfn;
         OCIBind *bnd;
@@ -300,15 +303,15 @@
     } u;
 };
 
-enum logon_type_t {T_NOT_LOGIN = 0, T_IMPLICIT, T_EXPLICIT};
 
-typedef struct  {
+typedef struct oci8_svcctx {
     oci8_base_t base;
     volatile VALUE executing_thread;
-    enum logon_type_t logon_type;
-    OCISession *authhp;
-    OCIServer *srvhp;
+    void (*logoff_method)(struct oci8_svcctx *svcctx);
+    oci8_base_t *session;
+    oci8_base_t *server;
     rb_pid_t pid;
+    unsigned char state;
     char is_autocommit;
 #ifdef RUBY_VM
     char non_blocking;

Modified: trunk/ruby-oci8/ext/oci8/ocihandle.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocihandle.c	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/ext/oci8/ocihandle.c	2010-05-04 12:59:37 UTC (rev 393)
@@ -2,7 +2,7 @@
 /*
  * ocihandle.c
  *
- * Copyright (C) 2009 KUBO Takehiro <kubo at jiubao.org>
+ * Copyright (C) 2009-2010 KUBO Takehiro <kubo at jiubao.org>
  *
  * implement OCIHandle
  *
@@ -91,6 +91,9 @@
     base->next = base;
     base->prev = base;
     base->children = NULL;
+    if (base_class->init != NULL) {
+        base_class->init(base);
+    }
     return obj;
 }
 
@@ -664,6 +667,7 @@
      *
      * OCIHandle is the abstract base class of OCI handles and
      * OCI descriptors; opaque data types of Oracle Call Interface.
+     * Don't use constants and methods defined in the class.
      */
     oci8_cOCIHandle = rb_define_class("OCIHandle", rb_cObject);
     rb_define_alloc_func(oci8_cOCIHandle, oci8_s_allocate);

Modified: trunk/ruby-oci8/lib/oci8/metadata.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/metadata.rb	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/lib/oci8/metadata.rb	2010-05-04 12:59:37 UTC (rev 393)
@@ -1,196 +1,13 @@
-# Implement OCI8::Metadata.
+# oci8.rb -- implements OCI8::Metadata.
+#
+# Copyright (C) 2006-2010 KUBO Takehiro <kubo at jiubao.org>
+#
 # See {'Describing Schema Metadata' in Oracle Call Interface Programmer's Guide}
 # [http://download-west.oracle.com/docs/cd/B19306_01/appdev.102/b14250/oci06des.htm]
 
 #
 class OCI8
 
-  # :stopdoc:
-
-  # Attribute Types in oci.h
-  OCI_ATTR_DATA_SIZE          =   1 # maximum size of the data
-  OCI_ATTR_DATA_TYPE          =   2 # the SQL type of the column/argument
-  OCI_ATTR_NAME               =   4 # the name of the column/argument
-  OCI_ATTR_PRECISION          =   5 # precision if number type
-  OCI_ATTR_SCALE              =   6 # scale if number type
-  OCI_ATTR_IS_NULL            =   7 # is it null ?
-  OCI_ATTR_TYPE_NAME          =   8 # name of the named data type or a package name
-  OCI_ATTR_SCHEMA_NAME        =   9 # the schema name
-  OCI_ATTR_SUB_NAME           =  10 # type name if package private type
-  OCI_ATTR_POSITION           =  11 # relative position
-  OCI_ATTR_PDSCL              =  16 # packed decimal scale
-  OCI_ATTR_FSPRECISION = OCI_ATTR_PDSCL # fs prec for datetime data types
-  OCI_ATTR_PDPRC              =  17 # packed decimal format
-  OCI_ATTR_LFPRECISION = OCI_ATTR_PDPRC # fs prec for datetime data types
-  OCI_ATTR_CHARSET_ID         =  31 # Character Set ID
-  OCI_ATTR_CHARSET_FORM       =  32 # Character Set Form
-  OCI_ATTR_NUM_COLS           = 102 # number of columns
-  OCI_ATTR_LIST_COLUMNS       = 103 # parameter of the column list
-  OCI_ATTR_RDBA               = 104 # DBA of the segment header
-  OCI_ATTR_CLUSTERED          = 105 # whether the table is clustered
-  OCI_ATTR_PARTITIONED        = 106 # whether the table is partitioned
-  OCI_ATTR_INDEX_ONLY         = 107 # whether the table is index only
-  OCI_ATTR_LIST_ARGUMENTS     = 108 # parameter of the argument list
-  OCI_ATTR_LIST_SUBPROGRAMS   = 109 # parameter of the subprogram list
-  OCI_ATTR_REF_TDO            = 110 # REF to the type descriptor
-  OCI_ATTR_LINK               = 111 # the database link name 
-  OCI_ATTR_MIN                = 112 # minimum value
-  OCI_ATTR_MAX                = 113 # maximum value
-  OCI_ATTR_INCR               = 114 # increment value
-  OCI_ATTR_CACHE              = 115 # number of sequence numbers cached
-  OCI_ATTR_ORDER              = 116 # whether the sequence is ordered
-  OCI_ATTR_HW_MARK            = 117 # high-water mark
-  OCI_ATTR_TYPE_SCHEMA        = 118 # type's schema name
-  OCI_ATTR_TIMESTAMP          = 119 # timestamp of the object
-  OCI_ATTR_NUM_PARAMS         = 121 # number of parameters
-  OCI_ATTR_OBJID              = 122 # object id for a table or view
-  OCI_ATTR_OVERLOAD_ID        = 125 # overload ID for funcs and procs
-  OCI_ATTR_TABLESPACE         = 126 # table name space
-  OCI_ATTR_LTYPE              = 128 # list type
-  OCI_ATTR_IS_TEMPORARY       = 130 # whether table is temporary
-  OCI_ATTR_IS_TYPED           = 131 # whether table is typed
-  OCI_ATTR_DURATION           = 132 # duration of temporary table
-  OCI_ATTR_IS_INVOKER_RIGHTS  = 133 # is invoker rights
-  OCI_ATTR_OBJ_NAME           = 134 # top level schema obj name
-  OCI_ATTR_OBJ_SCHEMA         = 135 # schema name
-  OCI_ATTR_OBJ_ID             = 136 # top level schema object id
-  # OCI_ATTR_OVERLOAD           = 210 # is this position overloaded
-  OCI_ATTR_LEVEL              = 211 # level for structured types
-  OCI_ATTR_HAS_DEFAULT        = 212 # has a default value
-  OCI_ATTR_IOMODE             = 213 # in, out inout
-  OCI_ATTR_RADIX              = 214 # returns a radix
-  # OCI_ATTR_NUM_ARGS           = 215 # total number of arguments
-  OCI_ATTR_TYPECODE           = 216 # object or collection
-  OCI_ATTR_COLLECTION_TYPECODE = 217 # varray or nested table
-  OCI_ATTR_VERSION            = 218 # user assigned version
-  OCI_ATTR_IS_INCOMPLETE_TYPE = 219 # is this an incomplete type
-  OCI_ATTR_IS_SYSTEM_TYPE     = 220 # a system type
-  OCI_ATTR_IS_PREDEFINED_TYPE = 221 # a predefined type
-  OCI_ATTR_IS_TRANSIENT_TYPE  = 222 # a transient type
-  OCI_ATTR_IS_SYSTEM_GENERATED_TYPE = 223 # system generated type
-  OCI_ATTR_HAS_NESTED_TABLE   = 224 # contains nested table attr
-  OCI_ATTR_HAS_LOB            = 225 # has a lob attribute
-  OCI_ATTR_HAS_FILE           = 226 # has a file attribute
-  OCI_ATTR_COLLECTION_ELEMENT = 227 # has a collection attribute
-  OCI_ATTR_NUM_TYPE_ATTRS     = 228 # number of attribute types
-  OCI_ATTR_LIST_TYPE_ATTRS    = 229 # list of type attributes
-  OCI_ATTR_NUM_TYPE_METHODS   = 230 # number of type methods
-  OCI_ATTR_LIST_TYPE_METHODS  = 231 # list of type methods
-  OCI_ATTR_MAP_METHOD         = 232 # map method of type
-  OCI_ATTR_ORDER_METHOD       = 233 # order method of type 
-  OCI_ATTR_NUM_ELEMS          = 234 # number of elements
-  OCI_ATTR_ENCAPSULATION      = 235 # encapsulation level
-  OCI_ATTR_IS_SELFISH         = 236 # method selfish
-  # OCI_ATTR_IS_VIRTUAL         = 237 # virtual
-  # OCI_ATTR_IS_INLINE          = 238 # inline
-  # OCI_ATTR_IS_CONSTANT        = 239 # constant
-  OCI_ATTR_HAS_RESULT         = 240 # has result
-  OCI_ATTR_IS_CONSTRUCTOR     = 241 # constructor
-  OCI_ATTR_IS_DESTRUCTOR      = 242 # destructor
-  # OCI_ATTR_IS_OPERATOR        = 243 # operator
-  OCI_ATTR_IS_MAP             = 244 # a map method
-  OCI_ATTR_IS_ORDER           = 245 # order method
-  OCI_ATTR_IS_RNDS            = 246 # read no data state method
-  OCI_ATTR_IS_RNPS            = 247 # read no process state
-  OCI_ATTR_IS_WNDS            = 248 # write no data state method
-  OCI_ATTR_IS_WNPS            = 249 # write no process state
-  OCI_ATTR_IS_SUBTYPE         = 258
-  OCI_ATTR_SUPERTYPE_SCHEMA_NAME = 259
-  OCI_ATTR_SUPERTYPE_NAME     = 260
-  OCI_ATTR_LIST_OBJECTS       = 261 # list of objects in schema
-  OCI_ATTR_NCHARSET_ID        = 262 # char set id
-  OCI_ATTR_LIST_SCHEMAS       = 263 # list of schemas
-  OCI_ATTR_MAX_PROC_LEN       = 264 # max procedure length
-  OCI_ATTR_MAX_COLUMN_LEN     = 265 # max column name length
-  OCI_ATTR_CURSOR_COMMIT_BEHAVIOR = 266 # cursor commit behavior
-  OCI_ATTR_MAX_CATALOG_NAMELEN = 267 # catalog namelength
-  OCI_ATTR_CATALOG_LOCATION   = 268 # catalog location
-  OCI_ATTR_SAVEPOINT_SUPPORT  = 269 # savepoint support
-  OCI_ATTR_NOWAIT_SUPPORT     = 270 # nowait support
-  OCI_ATTR_AUTOCOMMIT_DDL     = 271 # autocommit DDL
-  OCI_ATTR_LOCKING_MODE       = 272 # locking mode
-  # OCI_ATTR_CLIENT_IDENTIFIER  = 278 # value of client id to set
-  OCI_ATTR_IS_FINAL_TYPE      = 279 # is final type ?
-  OCI_ATTR_IS_INSTANTIABLE_TYPE = 280 # is instantiable type ?
-  OCI_ATTR_IS_FINAL_METHOD    = 281 # is final method ?
-  OCI_ATTR_IS_INSTANTIABLE_METHOD = 282 # is instantiable method ?
-  OCI_ATTR_IS_OVERRIDING_METHOD = 283 # is overriding method ?
-  # OCI_ATTR_DESC_SYNBASE       = 284 # Describe the base object
-  OCI_ATTR_CHAR_USED          = 285 # char length semantics
-  OCI_ATTR_CHAR_SIZE          = 286 # char length
-  OCI_ATTR_CONDITION          = 342 # rule condition
-  OCI_ATTR_COMMENT            = 343 # comment
-  OCI_ATTR_VALUE              = 344 # Anydata value
-  OCI_ATTR_EVAL_CONTEXT_OWNER = 345 # eval context owner
-  OCI_ATTR_EVAL_CONTEXT_NAME  = 346 # eval context name
-  OCI_ATTR_EVALUATION_FUNCTION = 347 # eval function name
-  OCI_ATTR_VAR_TYPE           = 348 # variable type
-  OCI_ATTR_VAR_VALUE_FUNCTION = 349 # variable value function
-  OCI_ATTR_VAR_METHOD_FUNCTION = 350 # variable method function
-  # OCI_ATTR_ACTION_CONTEXT     = 351 # action context
-  OCI_ATTR_LIST_TABLE_ALIASES = 352 # list of table aliases
-  OCI_ATTR_LIST_VARIABLE_TYPES = 353 # list of variable types
-  OCI_ATTR_TABLE_NAME         = 356 # table name
-
-  # OCI Parameter Types
-  OCI_PTYPE_UNK                =  0 # unknown
-  OCI_PTYPE_TABLE              =  1 # table
-  OCI_PTYPE_VIEW               =  2 # view
-  OCI_PTYPE_PROC               =  3 # procedure
-  OCI_PTYPE_FUNC               =  4 # function
-  OCI_PTYPE_PKG                =  5 # package
-  OCI_PTYPE_TYPE               =  6 # user-defined type
-  OCI_PTYPE_SYN                =  7 # synonym
-  OCI_PTYPE_SEQ                =  8 # sequence
-  OCI_PTYPE_COL                =  9 # column
-  OCI_PTYPE_ARG                = 10 # argument
-  OCI_PTYPE_LIST               = 11 # list
-  OCI_PTYPE_TYPE_ATTR          = 12 # user-defined type's attribute
-  OCI_PTYPE_TYPE_COLL          = 13 # collection type's element
-  OCI_PTYPE_TYPE_METHOD        = 14 # user-defined type's method
-  OCI_PTYPE_TYPE_ARG           = 15 # user-defined type method's arg
-  OCI_PTYPE_TYPE_RESULT        = 16 # user-defined type method's result
-  OCI_PTYPE_SCHEMA             = 17 # schema
-  OCI_PTYPE_DATABASE           = 18 # database
-  OCI_PTYPE_RULE               = 19 # rule
-  OCI_PTYPE_RULE_SET           = 20 # rule set
-  OCI_PTYPE_EVALUATION_CONTEXT = 21 # evaluation context
-  OCI_PTYPE_TABLE_ALIAS        = 22 # table alias
-  OCI_PTYPE_VARIABLE_TYPE      = 23 # variable type
-  OCI_PTYPE_NAME_VALUE         = 24 # name value pair
-
-  # OCI List Types
-  OCI_LTYPE_UNK                =  0 # unknown
-  OCI_LTYPE_COLUMN             =  1 # column list
-  OCI_LTYPE_ARG_PROC           =  2 # procedure argument list
-  OCI_LTYPE_ARG_FUNC           =  3 # function argument list
-  OCI_LTYPE_SUBPRG             =  4 # subprogram list
-  OCI_LTYPE_TYPE_ATTR          =  5 # type attribute
-  OCI_LTYPE_TYPE_METHOD        =  6 # type method
-  OCI_LTYPE_TYPE_ARG_PROC      =  7 # type method w/o result argument list
-  OCI_LTYPE_TYPE_ARG_FUNC      =  8 # type method w/result argument list
-  OCI_LTYPE_SCH_OBJ            =  9 # schema object list
-  OCI_LTYPE_DB_SCH             = 10 # database schema list
-  OCI_LTYPE_TYPE_SUBTYPE       = 11 # subtype list
-  OCI_LTYPE_TABLE_ALIAS        = 12 # table alias list
-  OCI_LTYPE_VARIABLE_TYPE      = 13 # variable type list
-  OCI_LTYPE_NAME_VALUE         = 14 # name value list
-
-  # OBJECT Duration in oro.h
-  OCI_DURATION_INVALID       = 0xFFFF
-  OCI_DURATION_BEGIN         = 10
-  OCI_DURATION_NULL          = OCI_DURATION_BEGIN - 1
-  OCI_DURATION_DEFAULT       = OCI_DURATION_BEGIN - 2
-  OCI_DURATION_USER_CALLBACK = OCI_DURATION_BEGIN - 3
-  OCI_DURATION_NEXT          = OCI_DURATION_BEGIN - 4
-  OCI_DURATION_SESSION       = OCI_DURATION_BEGIN
-  OCI_DURATION_TRANS         = OCI_DURATION_BEGIN + 1
-  OCI_DURATION_CALL          = OCI_DURATION_BEGIN + 2
-  OCI_DURATION_STATEMENT     = OCI_DURATION_BEGIN + 3
-  OCI_DURATION_CALLOUT       = OCI_DURATION_BEGIN + 4
-
-  # :startdoc:
-
   # = OCI8 can describe database object's metadata.
   # [user objects]
   #     OCI8#describe_any(object_name)

Modified: trunk/ruby-oci8/lib/oci8/oci8.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/oci8.rb	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/lib/oci8/oci8.rb	2010-05-04 12:59:37 UTC (rev 393)
@@ -1,6 +1,6 @@
 # oci8.rb -- implements OCI8 and OCI8::Cursor
 #
-# Copyright (C) 2002-2009 KUBO Takehiro <kubo at jiubao.org>
+# Copyright (C) 2002-2010 KUBO Takehiro <kubo at jiubao.org>
 #
 # Original Copyright is:
 #   Oracle module for Ruby
@@ -24,6 +24,110 @@
 #              value_for_the_first_parameter,
 #              value_for_the_second_parameter)
 class OCI8
+
+  # call-seq:
+  #   new(username, password, dbname = nil, privilege = nil)
+  #
+  # Connects to an Oracle database server by +username+ and +password+
+  # at +dbname+ as +privilege+.
+  #
+  # === connecting to the local server
+  #
+  # Set +username+ and +password+ or pass "username/password" as a
+  # single argument.
+  #
+  #   OCI8.new('scott', 'tiger')
+  # or
+  #   OCI8.new('scott/tiger')
+  #
+  # === connecting to a remote server
+  #
+  # Set +username+, +password+ and +dbname+ or pass
+  # "username/password at dbname" as a single argument.
+  #
+  #   OCI8.new('scott', 'tiger', 'orcl.world')
+  # or
+  #   OCI8.new('scott/tiger at orcl.world')
+  #
+  # The +dbname+ is a net service name or an easy connectection
+  # identifier. The former is a name listed in the file tnsnames.ora.
+  # Ask to your DBA if you don't know what it is. The latter has the
+  # syntax as "//host:port/service_name".
+  #
+  #   OCI8.new('scott', 'tiger', '//remote-host:1521/XE')
+  # or
+  #   OCI8.new('scott/tiger@//remote-host:1521/XE')
+  #
+  # === connecting as a privileged user
+  #
+  # Set :SYSDBA or :SYSOPER to +privilege+, otherwise
+  # "username/password as sysdba" or "username/password as sysoper"
+  # as a single argument.
+  #
+  #   OCI8.new('sys', 'change_on_install', nil, :SYSDBA)
+  # or
+  #   OCI8.new('sys/change_on_install as sysdba')
+  #
+  # === external OS authentication
+  #
+  # Set nil to +username+ and +password+, or "/" as a single argument.
+  #
+  #   OCI8.new(nil, nil)
+  # or
+  #   OCI8.new('/')
+  #
+  # To connect to a remote host:
+  #
+  #   OCI8.new(nil, nil, 'dbname')
+  # or
+  #   OCI8.new('/@dbname')
+  #
+  # === proxy authentication
+  #
+  # Enclose end user's username with square brackets and add it at the
+  # end of proxy user's username.
+  #
+  #   OCI8.new('proxy_user_name[end_user_name]', 'proxy_password')
+  # or
+  #   OCI8.new('proxy_user_name[end_user_name]/proxy_password')
+  #
+  def initialize(*args)
+    if args.length == 1
+      username, password, dbname, mode = parse_connect_string(args[0])
+    else
+      username, password, dbname, mode = args
+    end
+
+    if username.nil? and password.nil?
+      cred = OCI_CRED_EXT
+    end
+    case mode
+    when :SYSDBA
+      mode = OCI_SYSDBA
+    when :SYSOPER
+      mode = OCI_SYSOPER
+    when nil
+      # do nothing
+    else
+      raise "unknown privilege type #{mode}"
+    end
+
+    if mode.nil? and cred.nil?
+      # logon by the OCI function OCILogon().
+      logon(username, password, dbname)
+    else
+      # logon by the OCI function OCISessionBegin().
+      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, OCI_DEFAULT);
+      session_begin(cred ? cred : OCI_CRED_RDBMS, mode ? mode : OCI_DEFAULT)
+    end
+
+    @prefetch_rows = nil
+    @username = nil
+  end
+
   # Executes the sql statement. The type of return value depends on
   # the type of sql statement: select; insert, update and delete;
   # create, alter and drop; and PL/SQL.

Added: trunk/ruby-oci8/lib/oci8/ocihandle.rb
===================================================================
--- trunk/ruby-oci8/lib/oci8/ocihandle.rb	                        (rev 0)
+++ trunk/ruby-oci8/lib/oci8/ocihandle.rb	2010-05-04 12:59:37 UTC (rev 393)
@@ -0,0 +1,416 @@
+#--
+# ocihandle.rb -- Constants in OCIHandle.
+#
+# Copyright (C) 2010 KUBO Takehiro <kubo at jiubao.org>
+#++
+
+class OCIHandle
+
+  #################################
+  #
+  # Attribute Types in oci.h
+  #
+  #################################
+
+  # maximum size of the data
+  OCI_ATTR_DATA_SIZE          =   1
+
+  # the SQL type of the column/argument
+  OCI_ATTR_DATA_TYPE          =   2
+  # the name of the column/argument
+  OCI_ATTR_NAME               =   4
+  # precision if number type
+  OCI_ATTR_PRECISION          =   5
+  # scale if number type
+  OCI_ATTR_SCALE              =   6
+  # is it null ?
+  OCI_ATTR_IS_NULL            =   7
+  # name of the named data type or a package name
+  OCI_ATTR_TYPE_NAME          =   8
+  # the schema name
+  OCI_ATTR_SCHEMA_NAME        =   9
+  # type name if package private type
+  OCI_ATTR_SUB_NAME           =  10
+  # relative position
+  OCI_ATTR_POSITION           =  11
+  # packed decimal scale
+  OCI_ATTR_PDSCL              =  16
+  # fs prec for datetime data types
+  OCI_ATTR_FSPRECISION        = OCI_ATTR_PDSCL
+  # packed decimal format
+  OCI_ATTR_PDPRC              =  17
+  # fs prec for datetime data types
+  OCI_ATTR_LFPRECISION        = OCI_ATTR_PDPRC
+  # username attribute
+  OCI_ATTR_USERNAME           =  22
+  # password attribute
+  OCI_ATTR_PASSWORD           =  23
+  # Character Set ID
+  OCI_ATTR_CHARSET_ID         =  31
+  # Character Set Form
+  OCI_ATTR_CHARSET_FORM       =  32
+  # number of columns
+  OCI_ATTR_NUM_COLS           = 102
+  # parameter of the column list
+  OCI_ATTR_LIST_COLUMNS       = 103
+  # DBA of the segment header
+  OCI_ATTR_RDBA               = 104
+  # whether the table is clustered
+  OCI_ATTR_CLUSTERED          = 105
+  # whether the table is partitioned
+  OCI_ATTR_PARTITIONED        = 106
+  # whether the table is index only
+  OCI_ATTR_INDEX_ONLY         = 107
+  # parameter of the argument list
+  OCI_ATTR_LIST_ARGUMENTS     = 108
+  # parameter of the subprogram list
+  OCI_ATTR_LIST_SUBPROGRAMS   = 109
+  # REF to the type descriptor
+  OCI_ATTR_REF_TDO            = 110
+  # the database link name 
+  OCI_ATTR_LINK               = 111
+  # minimum value
+  OCI_ATTR_MIN                = 112
+  # maximum value
+  OCI_ATTR_MAX                = 113
+  # increment value
+  OCI_ATTR_INCR               = 114
+  # number of sequence numbers cached
+  OCI_ATTR_CACHE              = 115
+  # whether the sequence is ordered
+  OCI_ATTR_ORDER              = 116
+  # high-water mark
+  OCI_ATTR_HW_MARK            = 117
+  # type's schema name
+  OCI_ATTR_TYPE_SCHEMA        = 118
+  # timestamp of the object
+  OCI_ATTR_TIMESTAMP          = 119
+  # number of parameters
+  OCI_ATTR_NUM_PARAMS         = 121
+  # object id for a table or view
+  OCI_ATTR_OBJID              = 122
+  # overload ID for funcs and procs
+  OCI_ATTR_OVERLOAD_ID        = 125
+  # table name space
+  OCI_ATTR_TABLESPACE         = 126
+  # list type
+  OCI_ATTR_LTYPE              = 128
+  # whether table is temporary
+  OCI_ATTR_IS_TEMPORARY       = 130
+  # whether table is typed
+  OCI_ATTR_IS_TYPED           = 131
+  # duration of temporary table
+  OCI_ATTR_DURATION           = 132
+  # is invoker rights
+  OCI_ATTR_IS_INVOKER_RIGHTS  = 133
+  # top level schema obj name
+  OCI_ATTR_OBJ_NAME           = 134
+  # schema name
+  OCI_ATTR_OBJ_SCHEMA         = 135
+  # top level schema object id
+  OCI_ATTR_OBJ_ID             = 136
+
+  OCI_ATTR_CONN_NOWAIT        = 178
+  OCI_ATTR_CONN_BUSY_COUNT    = 179
+  OCI_ATTR_CONN_OPEN_COUNT    = 180
+  OCI_ATTR_CONN_TIMEOUT       = 181
+  OCI_ATTR_CONN_MIN           = 183
+  OCI_ATTR_CONN_MAX           = 184
+  OCI_ATTR_CONN_INCR          = 185
+
+  # is this position overloaded
+  OCI_ATTR_OVERLOAD           = 210
+  # level for structured types
+  OCI_ATTR_LEVEL              = 211
+  # has a default value
+  OCI_ATTR_HAS_DEFAULT        = 212
+  # in, out inout
+  OCI_ATTR_IOMODE             = 213
+  # returns a radix
+  OCI_ATTR_RADIX              = 214
+  # total number of arguments
+  OCI_ATTR_NUM_ARGS           = 215
+  # object or collection
+  OCI_ATTR_TYPECODE           = 216
+  # varray or nested table
+  OCI_ATTR_COLLECTION_TYPECODE = 217
+  # user assigned version
+  OCI_ATTR_VERSION            = 218
+  # is this an incomplete type
+  OCI_ATTR_IS_INCOMPLETE_TYPE = 219
+  # a system type
+  OCI_ATTR_IS_SYSTEM_TYPE     = 220
+  # a predefined type
+  OCI_ATTR_IS_PREDEFINED_TYPE = 221
+  # a transient type
+  OCI_ATTR_IS_TRANSIENT_TYPE  = 222
+  # system generated type
+  OCI_ATTR_IS_SYSTEM_GENERATED_TYPE = 223
+  # contains nested table attr
+  OCI_ATTR_HAS_NESTED_TABLE   = 224
+  # has a lob attribute
+  OCI_ATTR_HAS_LOB            = 225
+  # has a file attribute
+  OCI_ATTR_HAS_FILE           = 226
+  # has a collection attribute
+  OCI_ATTR_COLLECTION_ELEMENT = 227
+  # number of attribute types
+  OCI_ATTR_NUM_TYPE_ATTRS     = 228
+  # list of type attributes
+  OCI_ATTR_LIST_TYPE_ATTRS    = 229
+  # number of type methods
+  OCI_ATTR_NUM_TYPE_METHODS   = 230
+  # list of type methods
+  OCI_ATTR_LIST_TYPE_METHODS  = 231
+  # map method of type
+  OCI_ATTR_MAP_METHOD         = 232
+  # order method of type 
+  OCI_ATTR_ORDER_METHOD       = 233
+  # number of elements
+  OCI_ATTR_NUM_ELEMS          = 234
+  # encapsulation level
+  OCI_ATTR_ENCAPSULATION      = 235
+  # method selfish
+  OCI_ATTR_IS_SELFISH         = 236
+  # virtual
+  OCI_ATTR_IS_VIRTUAL         = 237
+  # inline
+  OCI_ATTR_IS_INLINE          = 238
+  # constant
+  OCI_ATTR_IS_CONSTANT        = 239
+  # has result
+  OCI_ATTR_HAS_RESULT         = 240
+  # constructor
+  OCI_ATTR_IS_CONSTRUCTOR     = 241
+  # destructor
+  OCI_ATTR_IS_DESTRUCTOR      = 242
+  # operator
+  OCI_ATTR_IS_OPERATOR        = 243
+  # a map method
+  OCI_ATTR_IS_MAP             = 244
+  # order method
+  OCI_ATTR_IS_ORDER           = 245
+  # read no data state method
+  OCI_ATTR_IS_RNDS            = 246
+  # read no process state
+  OCI_ATTR_IS_RNPS            = 247
+  # write no data state method
+  OCI_ATTR_IS_WNDS            = 248
+  # write no process state
+  OCI_ATTR_IS_WNPS            = 249
+  OCI_ATTR_IS_SUBTYPE         = 258
+  OCI_ATTR_SUPERTYPE_SCHEMA_NAME = 259
+  OCI_ATTR_SUPERTYPE_NAME     = 260
+  # list of objects in schema
+  OCI_ATTR_LIST_OBJECTS       = 261
+  # char set id
+  OCI_ATTR_NCHARSET_ID        = 262
+  # list of schemas
+  OCI_ATTR_LIST_SCHEMAS       = 263
+  # max procedure length
+  OCI_ATTR_MAX_PROC_LEN       = 264
+  # max column name length
+  OCI_ATTR_MAX_COLUMN_LEN     = 265
+  # cursor commit behavior
+  OCI_ATTR_CURSOR_COMMIT_BEHAVIOR = 266
+  # catalog namelength
+  OCI_ATTR_MAX_CATALOG_NAMELEN = 267
+  # catalog location
+  OCI_ATTR_CATALOG_LOCATION   = 268
+  # savepoint support
+  OCI_ATTR_SAVEPOINT_SUPPORT  = 269
+  # nowait support
+  OCI_ATTR_NOWAIT_SUPPORT     = 270
+  # autocommit DDL
+  OCI_ATTR_AUTOCOMMIT_DDL     = 271
+  # locking mode
+  OCI_ATTR_LOCKING_MODE       = 272
+  # value of client id to set
+  OCI_ATTR_CLIENT_IDENTIFIER  = 278
+  # is final type ?
+  OCI_ATTR_IS_FINAL_TYPE      = 279
+  # is instantiable type ?
+  OCI_ATTR_IS_INSTANTIABLE_TYPE = 280
+  # is final method ?
+  OCI_ATTR_IS_FINAL_METHOD    = 281
+  # is instantiable method ?
+  OCI_ATTR_IS_INSTANTIABLE_METHOD = 282
+  # is overriding method ?
+  OCI_ATTR_IS_OVERRIDING_METHOD = 283
+  # Describe the base object
+  OCI_ATTR_DESC_SYNBASE       = 284
+  # char length semantics
+  OCI_ATTR_CHAR_USED          = 285
+  # char length
+  OCI_ATTR_CHAR_SIZE          = 286
+  # rule condition
+  OCI_ATTR_CONDITION          = 342
+  # comment
+  OCI_ATTR_COMMENT            = 343
+  # Anydata value
+  OCI_ATTR_VALUE              = 344
+  # eval context owner
+  OCI_ATTR_EVAL_CONTEXT_OWNER = 345
+  # eval context name
+  OCI_ATTR_EVAL_CONTEXT_NAME  = 346
+  # eval function name
+  OCI_ATTR_EVALUATION_FUNCTION = 347
+  # variable type
+  OCI_ATTR_VAR_TYPE           = 348
+  # variable value function
+  OCI_ATTR_VAR_VALUE_FUNCTION = 349
+  # variable method function
+  OCI_ATTR_VAR_METHOD_FUNCTION = 350
+  # action context
+  OCI_ATTR_ACTION_CONTEXT     = 351
+  # list of table aliases
+  OCI_ATTR_LIST_TABLE_ALIASES = 352
+  # list of variable types
+  OCI_ATTR_LIST_VARIABLE_TYPES = 353
+  # table name
+  OCI_ATTR_TABLE_NAME         = 356
+
+  #################################
+  #
+  # Various Modes
+  #
+  #################################
+
+  # the default value for parameters and attributes
+  OCI_DEFAULT                 =   0
+
+  #################################
+  #
+  # Credential Types
+  #
+  #################################
+
+  # database username/password credentials
+  OCI_CRED_RDBMS              =   1
+  # externally provided credentials
+  OCI_CRED_EXT                =   2
+
+  #################################
+  #
+  # Authentication Modes
+  #
+  #################################
+
+  # for SYSDBA authorization
+  OCI_SYSDBA                  = 0x0002
+  # for SYSOPER authorization
+  OCI_SYSOPER                 = 0x0004
+
+  #################################
+  #
+  # OCI Parameter Types
+  #
+  #################################
+
+  # parameter type for unknown type
+  OCI_PTYPE_UNK               =  0
+  # parameter type for table
+  OCI_PTYPE_TABLE             =  1
+  # parameter type for view
+  OCI_PTYPE_VIEW              =  2
+  # parameter type for procedure
+  OCI_PTYPE_PROC              =  3
+  # parameter type for function
+  OCI_PTYPE_FUNC              =  4
+  # parameter type for package
+  OCI_PTYPE_PKG               =  5
+  # parameter type for user-defined type
+  OCI_PTYPE_TYPE              =  6
+  # parameter type for synonym
+  OCI_PTYPE_SYN               =  7
+  # parameter type for sequence
+  OCI_PTYPE_SEQ               =  8
+  # parameter type for column
+  OCI_PTYPE_COL               =  9
+  # parameter type for argument
+  OCI_PTYPE_ARG               = 10
+  # parameter type for list
+  OCI_PTYPE_LIST              = 11
+  # parameter type for user-defined type's attribute
+  OCI_PTYPE_TYPE_ATTR         = 12
+  # parameter type for collection type's element
+  OCI_PTYPE_TYPE_COLL         = 13
+  # parameter type for user-defined type's method
+  OCI_PTYPE_TYPE_METHOD       = 14
+  # parameter type for user-defined type method's arg
+  OCI_PTYPE_TYPE_ARG          = 15
+  # parameter type for user-defined type method's result
+  OCI_PTYPE_TYPE_RESULT       = 16
+  # parameter type for schema
+  OCI_PTYPE_SCHEMA            = 17
+  # parameter type for database
+  OCI_PTYPE_DATABASE          = 18
+  # parameter type for rule
+  OCI_PTYPE_RULE              = 19
+  # parameter type for rule set
+  OCI_PTYPE_RULE_SET          = 20
+  # parameter type for evaluation context
+  OCI_PTYPE_EVALUATION_CONTEXT = 21
+  # parameter type for table alias
+  OCI_PTYPE_TABLE_ALIAS       = 22
+  # parameter type for variable type
+  OCI_PTYPE_VARIABLE_TYPE     = 23
+  # parameter type for name value pair
+  OCI_PTYPE_NAME_VALUE        = 24
+
+  #################################
+  #
+  # OCI List Types
+  #
+  #################################
+
+  # list type for unknown type
+  OCI_LTYPE_UNK                =  0
+  # list type for column list
+  OCI_LTYPE_COLUMN             =  1
+  # list type for procedure argument list
+  OCI_LTYPE_ARG_PROC           =  2
+  # list type for function argument list
+  OCI_LTYPE_ARG_FUNC           =  3
+  # list type for subprogram list
+  OCI_LTYPE_SUBPRG             =  4
+  # list type for type attribute
+  OCI_LTYPE_TYPE_ATTR          =  5
+  # list type for type method
+  OCI_LTYPE_TYPE_METHOD        =  6
+  # list type for type method w/o result argument list
+  OCI_LTYPE_TYPE_ARG_PROC      =  7
+  # list type for type method w/result argument list
+  OCI_LTYPE_TYPE_ARG_FUNC      =  8
+  # list type for schema object list
+  OCI_LTYPE_SCH_OBJ            =  9
+  # list type for database schema list
+  OCI_LTYPE_DB_SCH             = 10
+  # list type for subtype list
+  OCI_LTYPE_TYPE_SUBTYPE       = 11
+  # list type for table alias list
+  OCI_LTYPE_TABLE_ALIAS        = 12
+  # list type for variable type list
+  OCI_LTYPE_VARIABLE_TYPE      = 13
+  # list type for name value list
+  OCI_LTYPE_NAME_VALUE         = 14
+
+  #################################
+  #
+  # OBJECT Duration in oro.h
+  #
+  #################################
+
+  #
+  OCI_DURATION_INVALID       = 0xFFFF
+  OCI_DURATION_BEGIN         = 10
+  OCI_DURATION_NULL          = OCI_DURATION_BEGIN - 1
+  OCI_DURATION_DEFAULT       = OCI_DURATION_BEGIN - 2
+  OCI_DURATION_USER_CALLBACK = OCI_DURATION_BEGIN - 3
+  OCI_DURATION_NEXT          = OCI_DURATION_BEGIN - 4
+  OCI_DURATION_SESSION       = OCI_DURATION_BEGIN
+  OCI_DURATION_TRANS         = OCI_DURATION_BEGIN + 1
+  OCI_DURATION_CALL          = OCI_DURATION_BEGIN + 2
+  OCI_DURATION_STATEMENT     = OCI_DURATION_BEGIN + 3
+  OCI_DURATION_CALLOUT       = OCI_DURATION_BEGIN + 4
+end

Modified: trunk/ruby-oci8/lib/oci8.rb.in
===================================================================
--- trunk/ruby-oci8/lib/oci8.rb.in	2010-05-03 13:55:17 UTC (rev 392)
+++ trunk/ruby-oci8/lib/oci8.rb.in	2010-05-04 12:59:37 UTC (rev 393)
@@ -62,6 +62,7 @@
   end
 end
 
+require 'oci8/ocihandle.rb'
 require 'oci8/datetime.rb'
 require 'oci8/oci8.rb'
 require 'oci8/bindtype.rb'




More information about the ruby-oci8-commit mailing list