[ruby-oci8-commit] [380] trunk/ruby-oci8: * ext/oci8/apiwrap.yml, ext/oci8/error.c, ext/oci8/ oci8.h,

nobody at rubyforge.org nobody at rubyforge.org
Sat Feb 27 05:43:28 EST 2010


Revision: 380
Author:   kubo
Date:     2010-02-27 05:43:28 -0500 (Sat, 27 Feb 2010)

Log Message:
-----------
* ext/oci8/apiwrap.yml, ext/oci8/error.c, ext/oci8/oci8.h,
  ext/oci8/ocinumber.c: fix for Oracle 8.0 client, which doesn't
    have OCIMessageOpen() and OCIMessageGet().
* ext/oci8/oci8.c: add a new method OCI8.error_message to get
    a error message which depends on NLS_LANGUAGE.

Modified Paths:
--------------
    trunk/ruby-oci8/ChangeLog
    trunk/ruby-oci8/ext/oci8/apiwrap.yml
    trunk/ruby-oci8/ext/oci8/error.c
    trunk/ruby-oci8/ext/oci8/oci8.c
    trunk/ruby-oci8/ext/oci8/oci8.h
    trunk/ruby-oci8/ext/oci8/ocinumber.c

Modified: trunk/ruby-oci8/ChangeLog
===================================================================
--- trunk/ruby-oci8/ChangeLog	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ChangeLog	2010-02-27 10:43:28 UTC (rev 380)
@@ -1,3 +1,10 @@
+2010-02-27  KUBO Takehiro  <kubo at jiubao.org>
+	* ext/oci8/apiwrap.yml, ext/oci8/error.c, ext/oci8/oci8.h,
+	  ext/oci8/ocinumber.c: fix for Oracle 8.0 client, which doesn't
+	    have OCIMessageOpen() and OCIMessageGet().
+	* ext/oci8/oci8.c: add a new method OCI8.error_message to get
+	    a error message which depends on NLS_LANGUAGE.
+
 2010-02-09  KUBO Takehiro  <kubo at jiubao.org>
 	* dist-files: add ext/oci8/oranumber_util.c and
 	    ext/oci8/oranumber_util.h.

Modified: trunk/ruby-oci8/ext/oci8/apiwrap.yml
===================================================================
--- trunk/ruby-oci8/ext/oci8/apiwrap.yml	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ext/oci8/apiwrap.yml	2010-02-27 10:43:28 UTC (rev 380)
@@ -947,6 +947,23 @@
             - OCILobLocator *locp
             - ub1 mode
 
+OCIMessageOpen:
+  :version: 810
+  :args:    - dvoid *envhp
+            - OCIError *errhp
+            - OCIMsg **msghp
+            - CONST OraText *product
+            - CONST OraText *facility
+            - OCIDuration dur
+
+OCIMessageGet:
+  :version: 810
+  :ret:     OraText *
+  :args:    - OCIMsg *msgh
+            - ub4 msgno
+            - OraText *msgbuf
+            - size_t buflen
+
 # round trip: 0
 OCINumberIsInt:
   :version: 810

Modified: trunk/ruby-oci8/ext/oci8/error.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/error.c	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ext/oci8/error.c	2010-02-27 10:43:28 UTC (rev 380)
@@ -350,26 +350,36 @@
     set_backtrace_and_raise(exc, file, line);
 }
 
-static VALUE get_error_msg_by_msgno(ub4 msgno)
+VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
 {
-    char buf[256];
-    int sz;
+    char head[32];
+    size_t headsz;
+    const char *errmsg = NULL;
+    char msgbuf[64];
 
-    if (msghp == NULL) {
-        OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_ORATEXT("rdbms"), TO_ORATEXT("ora"), OCI_DURATION_PROCESS);
+    if (have_OCIMessageGet) {
+        if (msghp == NULL) {
+            oci_lc(OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_ORATEXT("rdbms"), TO_ORATEXT("ora"), OCI_DURATION_PROCESS));
+        }
+        errmsg = TO_CHARPTR(OCIMessageGet(msghp, msgno, NULL, 0));
     }
-
-    sz = snprintf(buf, sizeof(buf), "ORA-%05u: ", msgno);
-    if (msghp == NULL || OCIMessageGet(msghp, msgno, TO_ORATEXT(buf + sz), sizeof(buf) - sz) == NULL) {
-        strcpy(buf + sz, "could not get the error message");
+    if (errmsg == NULL) {
+        if (default_msg != NULL) {
+            errmsg = default_msg;
+        } else {
+            /* last resort */
+            snprintf(msgbuf, sizeof(msgbuf), "Message %u not found;  product=rdbms; facility=ora", msgno);
+            errmsg = msgbuf;
+        }
     }
-    return rb_external_str_new_with_enc(buf, strlen(buf), oci8_encoding);
-
+    headsz = snprintf(head, sizeof(head), "ORA-%05u: ", msgno);
+    return rb_str_append(rb_usascii_str_new(head, headsz),
+                         rb_external_str_new_with_enc(errmsg, strlen(errmsg), oci8_encoding));
 }
 
-void oci8_do_raise_by_msgno(ub4 msgno, const char *file, int line)
+void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
 {
-    VALUE msg = get_error_msg_by_msgno(msgno);
+    VALUE msg = oci8_get_error_message(msgno, default_msg);
     VALUE exc = rb_funcall(eOCIError, oci8_id_new, 1, msg);
 
     rb_ivar_set(exc, oci8_id_code, rb_ary_new3(1, INT2FIX(-1)));

Modified: trunk/ruby-oci8/ext/oci8/oci8.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.c	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ext/oci8/oci8.c	2010-02-27 10:43:28 UTC (rev 380)
@@ -64,6 +64,28 @@
     return oracle_client_vernum;
 }
 
+/*
+ * call-seq:
+ *   OCI8.error_message(message_no) -> string
+ *
+ * Get the Oracle error message specified by message_no.
+ * Its language depends on NLS_LANGUAGE.
+ *
+ * Note: This method is unavailable if the Oracle client version is 8.0.
+ *
+ * example:
+ *   # When NLS_LANG is american_america.AL32UTF8
+ *   OCI8.error_message(1) # => "ORA-00001: unique constraint (%s.%s) violated"
+ *   
+ *   # When NLS_LANG is french_japan.AL32UTF8
+ *   OCI8.error_message(1) # => "ORA-00001: violation de contrainte unique (%s.%s)"
+ *
+ */
+static VALUE oci8_s_error_message(VALUE klass, VALUE msgid)
+{
+    return oci8_get_error_message(NUM2UINT(msgid), NULL);
+}
+
 #define CONN_STR_REGEX "/^([^(\\s|\\@)]*)\\/([^(\\s|\\@)]*)(?:\\@(\\S+))?(?:\\s+as\\s+(\\S*)\\s*)?$/i"
 static void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode)
 {
@@ -942,6 +964,9 @@
     id_set_prefetch_rows = rb_intern("prefetch_rows=");
 
     rb_define_singleton_method_nodoc(cOCI8, "oracle_client_vernum", oci8_s_oracle_client_vernum, 0);
+    if (have_OCIMessageOpen && have_OCIMessageGet) {
+        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_method(cOCI8, "logoff", oci8_svcctx_logoff, 0);

Modified: trunk/ruby-oci8/ext/oci8/oci8.h
===================================================================
--- trunk/ruby-oci8/ext/oci8/oci8.h	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ext/oci8/oci8.h	2010-02-27 10:43:28 UTC (rev 380)
@@ -336,7 +336,7 @@
 #define oci8_raise(err, status, stmt) oci8_do_raise(err, status, stmt, __FILE__, __LINE__)
 #define oci8_env_raise(err, status) oci8_do_env_raise(err, status, __FILE__, __LINE__)
 #define oci8_raise_init_error() oci8_do_raise_init_error(__FILE__, __LINE__)
-#define oci8_raise_by_msgno(msgno) oci8_do_raise_by_msgno(msgno, __FILE__, __LINE__)
+#define oci8_raise_by_msgno(msgno, default_msg) oci8_do_raise_by_msgno(msgno, default_msg, __FILE__, __LINE__)
 
 /* raise on error */
 #define oci_lc(rv) do { \
@@ -413,7 +413,8 @@
 NORETURN(void oci8_do_env_raise(OCIEnv *, sword status, const char *file, int line));
 NORETURN(void oci8_do_raise_init_error(const char *file, int line));
 sb4 oci8_get_error_code(OCIError *errhp);
-NORETURN(void oci8_do_raise_by_msgno(ub4 msgno, const char *file, int line));
+VALUE oci8_get_error_message(ub4 msgno, const char *default_msg);
+NORETURN(void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line));
 
 /* ocihandle.c */
 void Init_oci8_handle(void);

Modified: trunk/ruby-oci8/ext/oci8/ocinumber.c
===================================================================
--- trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-02-09 10:45:56 UTC (rev 379)
+++ trunk/ruby-oci8/ext/oci8/ocinumber.c	2010-02-27 10:43:28 UTC (rev 380)
@@ -154,7 +154,16 @@
         if (rv == ORANUMBER_SUCCESS) {
             return; /* success */
         } else {
-            oci8_raise_by_msgno(rv);
+            const char *default_msg = NULL;
+            switch (rv) {
+            case ORANUMBER_INVALID_NUMBER:
+                default_msg = "invalid number";
+                break;
+            case ORANUMBER_NUMERIC_OVERFLOW:
+                default_msg = "numeric overflow";
+                break;
+            }
+            oci8_raise_by_msgno(rv, default_msg);
         }
     }
     StringValue(fmt);




More information about the ruby-oci8-commit mailing list