From nobody at rubyforge.org Sun Jan 24 08:43:12 2010 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 24 Jan 2010 08:43:12 -0500 (EST) Subject: [ruby-oci8-commit] [374] trunk/ruby-oci8: * ext/oci8/error.c: Use OCIErrorGet() to retrieve the error message Message-ID: <20100124134312.2DE921D788BA@rubyforge.org> Revision: 374 Author: kubo Date: 2010-01-24 08:43:11 -0500 (Sun, 24 Jan 2010) Log Message: ----------- * ext/oci8/error.c: Use OCIErrorGet() to retrieve the error message when the OCI return code is OCI_NO_DATA. (reported by Raimonds Simanovskis) Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/error.c Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2009-12-06 14:01:37 UTC (rev 373) +++ trunk/ruby-oci8/ChangeLog 2010-01-24 13:43:11 UTC (rev 374) @@ -1,3 +1,8 @@ +2010-01-24 KUBO Takehiro + * ext/oci8/error.c: Use OCIErrorGet() to retrieve the error message + when the OCI return code is OCI_NO_DATA. + (reported by Raimonds Simanovskis) + 2009-12-06 KUBO Takehiro * ext/oci8/object.c: 1. fix segv when GC starts while initializing a bind object for object type. (reported by Remi Gagnon) Modified: trunk/ruby-oci8/ext/oci8/error.c =================================================================== --- trunk/ruby-oci8/ext/oci8/error.c 2009-12-06 14:01:37 UTC (rev 373) +++ trunk/ruby-oci8/ext/oci8/error.c 2010-01-24 13:43:11 UTC (rev 374) @@ -2,7 +2,7 @@ /* error.c - part of ruby-oci8 - Copyright (C) 2002-2007 KUBO Takehiro + Copyright (C) 2002-2010 KUBO Takehiro =begin == OCIError @@ -28,9 +28,52 @@ static ID oci8_id_caller; static ID oci8_id_set_backtrace; +#define ERRBUF_EXPAND_LEN 256 +static char *errbuf; +static ub4 errbufsiz; + NORETURN(static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)); NORETURN(static void set_backtrace_and_raise(VALUE exc, const char *file, int line)); +static VALUE get_error_msg(dvoid *errhp, ub4 type, const char *default_msg, sb4 *errcode_p) +{ + sword rv; + size_t len; + +retry: + errbuf[0] = '\0'; + rv = OCIErrorGet(errhp, 1, NULL, errcode_p, TO_ORATEXT(errbuf), errbufsiz, type); + /* OCI manual says: + * If type is set to OCI_HTYPE_ERROR, then the return + * code during truncation for OCIErrorGet() is + * OCI_ERROR. The client can then specify a bigger + * buffer and call OCIErrorGet() again. + * + * But as far as I tested on Oracle XE 10.2.0.1, the return + * code is OCI_SUCCESS when the message is truncated. + */ + len = strlen(errbuf); + if (errbufsiz - len <= 7) { + /* The error message may be truncated. + * The magic number 7 means the maximum length of one utf-8 + * character plus the length of a nul terminator. + */ + errbufsiz += ERRBUF_EXPAND_LEN; + errbuf = xrealloc(errbuf, errbufsiz); + goto retry; + } + if (rv != OCI_SUCCESS) { + /* No message is found. Use the default message. */ + return rb_usascii_str_new_cstr(default_msg); + } + + /* truncate trailing CR and LF */ + while (len > 0 && (errbuf[len - 1] == '\n' || errbuf[len - 1] == '\r')) { + len--; + } + return rb_external_str_new_with_enc(errbuf, len, oci8_encoding); +} + static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line) { VALUE vcodes = Qnil; @@ -103,7 +146,7 @@ break; case OCI_NO_DATA: exc = eOCINoData; - msg = rb_usascii_str_new_cstr("No Data"); + msg = get_error_msg(errhp, type, "No Data", &errcode); break; case OCI_INVALID_HANDLE: exc = eOCIInvalidHandle; @@ -252,6 +295,9 @@ void Init_oci8_error(void) { + errbufsiz = ERRBUF_EXPAND_LEN; + errbuf = xmalloc(errbufsiz); + oci8_id_code = rb_intern("code"); oci8_id_message = rb_intern("message"); oci8_id_parse_error_offset = rb_intern("parse_error_offset");