ruby-oci8-master 2.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ChangeLog +2321 -0
- data/Makefile +88 -0
- data/NEWS +303 -0
- data/README +76 -0
- data/VERSION +1 -0
- data/dist-files +83 -0
- data/doc/api.en.html +527 -0
- data/doc/api.en.rd +554 -0
- data/doc/api.ja.html +525 -0
- data/doc/api.ja.rd +557 -0
- data/doc/manual.css +35 -0
- data/ext/oci8/.document +18 -0
- data/ext/oci8/MANIFEST +18 -0
- data/ext/oci8/apiwrap.c.tmpl +182 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1455 -0
- data/ext/oci8/attr.c +105 -0
- data/ext/oci8/bind.c +366 -0
- data/ext/oci8/connection_pool.c +199 -0
- data/ext/oci8/encoding.c +289 -0
- data/ext/oci8/env.c +178 -0
- data/ext/oci8/error.c +378 -0
- data/ext/oci8/extconf.rb +179 -0
- data/ext/oci8/lob.c +805 -0
- data/ext/oci8/metadata.c +232 -0
- data/ext/oci8/object.c +727 -0
- data/ext/oci8/oci8.c +1156 -0
- data/ext/oci8/oci8.h +574 -0
- data/ext/oci8/oci8lib.c +527 -0
- data/ext/oci8/ocidatetime.c +484 -0
- data/ext/oci8/ocihandle.c +751 -0
- data/ext/oci8/ocinumber.c +1612 -0
- data/ext/oci8/oraconf.rb +1119 -0
- data/ext/oci8/oradate.c +611 -0
- data/ext/oci8/oranumber_util.c +352 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/post-config.rb +5 -0
- data/ext/oci8/stmt.c +673 -0
- data/ext/oci8/thread_util.c +85 -0
- data/ext/oci8/thread_util.h +30 -0
- data/ext/oci8/win32.c +137 -0
- data/lib/.document +1 -0
- data/lib/dbd/OCI8.rb +591 -0
- data/lib/oci8.rb.in +94 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +349 -0
- data/lib/oci8/compat.rb +113 -0
- data/lib/oci8/connection_pool.rb +99 -0
- data/lib/oci8/datetime.rb +611 -0
- data/lib/oci8/encoding-init.rb +74 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2132 -0
- data/lib/oci8/object.rb +581 -0
- data/lib/oci8/oci8.rb +721 -0
- data/lib/oci8/ocihandle.rb +425 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/lib/oci8/properties.rb +73 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +63 -0
- data/setup.rb +1331 -0
- data/test/README +4 -0
- data/test/config.rb +122 -0
- data/test/test_all.rb +51 -0
- data/test/test_appinfo.rb +63 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +46 -0
- data/test/test_bind_time.rb +178 -0
- data/test/test_break.rb +96 -0
- data/test/test_clob.rb +82 -0
- data/test/test_connstr.rb +81 -0
- data/test/test_datetime.rb +582 -0
- data/test/test_dbi.rb +366 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +100 -0
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1399 -0
- data/test/test_oci8.rb +434 -0
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +256 -0
- data/test/test_oranumber.rb +746 -0
- data/test/test_rowid.rb +33 -0
- metadata +137 -0
data/ext/oci8/env.c
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* env.c - part of ruby-oci8
|
4
|
+
*
|
5
|
+
* Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
|
6
|
+
*/
|
7
|
+
#include "oci8.h"
|
8
|
+
|
9
|
+
#if defined(HAVE_RUBY_UTIL_H)
|
10
|
+
#include <ruby/util.h>
|
11
|
+
#elif defined(HAVE_UTIL_H)
|
12
|
+
#include <util.h>
|
13
|
+
#endif
|
14
|
+
|
15
|
+
ub4 oci8_env_mode = OCI_OBJECT | OCI_THREADED;
|
16
|
+
|
17
|
+
OCIEnv *oci8_global_envhp;
|
18
|
+
|
19
|
+
OCIEnv *oci8_make_envhp(void)
|
20
|
+
{
|
21
|
+
sword rv;
|
22
|
+
|
23
|
+
rv = OCIEnvCreate(&oci8_global_envhp, oci8_env_mode, NULL, NULL, NULL, NULL, 0, NULL);
|
24
|
+
if (rv != OCI_SUCCESS) {
|
25
|
+
oci8_raise_init_error();
|
26
|
+
}
|
27
|
+
return oci8_global_envhp;
|
28
|
+
}
|
29
|
+
|
30
|
+
#ifdef USE_THREAD_LOCAL_ERRHP
|
31
|
+
/*
|
32
|
+
* Setup thread-local oci8_errhp.
|
33
|
+
*/
|
34
|
+
|
35
|
+
oci8_tls_key_t oci8_tls_key; /* native thread key */
|
36
|
+
|
37
|
+
/* This function is called on the native thread termination
|
38
|
+
* if the thread local errhp is not null.
|
39
|
+
*/
|
40
|
+
static void oci8_free_errhp(void *errhp)
|
41
|
+
{
|
42
|
+
OCIHandleFree(errhp, OCI_HTYPE_ERROR);
|
43
|
+
}
|
44
|
+
|
45
|
+
#ifdef _WIN32
|
46
|
+
static int dllmain_is_called;
|
47
|
+
|
48
|
+
__declspec(dllexport)
|
49
|
+
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
50
|
+
{
|
51
|
+
void *errhp;
|
52
|
+
|
53
|
+
switch (fdwReason) {
|
54
|
+
case DLL_PROCESS_ATTACH:
|
55
|
+
dllmain_is_called = 1;
|
56
|
+
break;
|
57
|
+
case DLL_THREAD_ATTACH:
|
58
|
+
/* do nothing */
|
59
|
+
break;
|
60
|
+
case DLL_THREAD_DETACH:
|
61
|
+
errhp = oci8_tls_get(oci8_tls_key);
|
62
|
+
if (errhp != NULL) {
|
63
|
+
oci8_free_errhp(errhp);
|
64
|
+
}
|
65
|
+
break;
|
66
|
+
case DLL_PROCESS_DETACH:
|
67
|
+
/* do nothing */
|
68
|
+
break;
|
69
|
+
}
|
70
|
+
return TRUE;
|
71
|
+
}
|
72
|
+
#endif
|
73
|
+
|
74
|
+
OCIError *oci8_make_errhp(void)
|
75
|
+
{
|
76
|
+
OCIError *errhp;
|
77
|
+
sword rv;
|
78
|
+
|
79
|
+
/* create a new errhp. */
|
80
|
+
rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&errhp, OCI_HTYPE_ERROR, 0, NULL);
|
81
|
+
if (rv != OCI_SUCCESS) {
|
82
|
+
oci8_env_raise(oci8_envhp, rv);
|
83
|
+
}
|
84
|
+
/* Set the errhp to the thread local storage.
|
85
|
+
* It is freed by oci8_free_errhp().
|
86
|
+
*/
|
87
|
+
oci8_tls_set(oci8_tls_key, (void*)errhp);
|
88
|
+
return errhp;
|
89
|
+
}
|
90
|
+
#else
|
91
|
+
/*
|
92
|
+
* oci8_errhp is global in ruby 1.8 configured without --enable-pthread on Unix.
|
93
|
+
*/
|
94
|
+
OCIError *oci8_global_errhp;
|
95
|
+
|
96
|
+
OCIError *oci8_make_errhp(void)
|
97
|
+
{
|
98
|
+
sword rv;
|
99
|
+
|
100
|
+
rv = OCIHandleAlloc(oci8_envhp, (dvoid *)&oci8_global_errhp, OCI_HTYPE_ERROR, 0, NULL);
|
101
|
+
if (rv != OCI_SUCCESS)
|
102
|
+
oci8_env_raise(oci8_envhp, rv);
|
103
|
+
return oci8_global_errhp;
|
104
|
+
}
|
105
|
+
#endif
|
106
|
+
|
107
|
+
void Init_oci8_env(void)
|
108
|
+
{
|
109
|
+
#ifdef USE_THREAD_LOCAL_ERRHP
|
110
|
+
int error;
|
111
|
+
#endif
|
112
|
+
|
113
|
+
#if !defined(HAVE_RB_THREAD_BLOCKING_REGION) && !defined(_WIN32)
|
114
|
+
/* workaround code.
|
115
|
+
*
|
116
|
+
* Some instant clients set the environment variables
|
117
|
+
* ORA_NLS_PROFILE33, ORA_NLS10 and ORACLE_HOME if they aren't
|
118
|
+
* set. It causes problems on some platforms.
|
119
|
+
*/
|
120
|
+
if (RTEST(rb_eval_string("RUBY_VERSION == \"1.8.4\""))) {
|
121
|
+
if (getenv("ORA_NLS_PROFILE33") == NULL) {
|
122
|
+
ruby_setenv("ORA_NLS_PROFILE33", "");
|
123
|
+
}
|
124
|
+
if (getenv("ORA_NLS10") == NULL) {
|
125
|
+
ruby_setenv("ORA_NLS10", "");
|
126
|
+
}
|
127
|
+
if (getenv("ORACLE_HOME") == NULL) {
|
128
|
+
ruby_setenv("ORACLE_HOME", ".");
|
129
|
+
}
|
130
|
+
}
|
131
|
+
#endif /* WIN32 */
|
132
|
+
|
133
|
+
/* workaround code.
|
134
|
+
*
|
135
|
+
* When ORACLE_HOME ends with '/' and the Oracle client is
|
136
|
+
* an instant client lower than 10.2.0.3, OCIEvnCreate()
|
137
|
+
* doesn't work even though the combination of OCIInitialize()
|
138
|
+
* and OCIEnvInit() works fine. Delete the last slash for
|
139
|
+
* a workaround.
|
140
|
+
*/
|
141
|
+
if (oracle_client_version < ORAVERNUM(10, 2, 0, 3, 0)) {
|
142
|
+
#ifdef _WIN32
|
143
|
+
#define DIR_SEP '\\'
|
144
|
+
#else
|
145
|
+
#define DIR_SEP '/'
|
146
|
+
#endif
|
147
|
+
char *home = getenv("ORACLE_HOME");
|
148
|
+
if (home != NULL) {
|
149
|
+
size_t homelen = strlen(home);
|
150
|
+
if (homelen > 0 && home[homelen - 1] == DIR_SEP) {
|
151
|
+
home = ruby_strdup(home);
|
152
|
+
home[homelen - 1] = '\0';
|
153
|
+
ruby_setenv("ORACLE_HOME", home);
|
154
|
+
xfree(home);
|
155
|
+
}
|
156
|
+
}
|
157
|
+
}
|
158
|
+
|
159
|
+
#ifdef USE_THREAD_LOCAL_ERRHP
|
160
|
+
#if defined(_WIN32)
|
161
|
+
if (!dllmain_is_called) {
|
162
|
+
/* sanity check */
|
163
|
+
rb_raise(rb_eRuntimeError, "DllMain is not unexpectedly called. This causes resource leaks.");
|
164
|
+
}
|
165
|
+
oci8_tls_key = TlsAlloc();
|
166
|
+
if (oci8_tls_key == 0xFFFFFFFF) {
|
167
|
+
error = GetLastError();
|
168
|
+
} else {
|
169
|
+
error = 0;
|
170
|
+
}
|
171
|
+
#else
|
172
|
+
error = pthread_key_create(&oci8_tls_key, oci8_free_errhp);
|
173
|
+
#endif
|
174
|
+
if (error != 0) {
|
175
|
+
rb_raise(rb_eRuntimeError, "Cannot create thread local key (errno = %d)", error);
|
176
|
+
}
|
177
|
+
#endif
|
178
|
+
}
|
data/ext/oci8/error.c
ADDED
@@ -0,0 +1,378 @@
|
|
1
|
+
/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
error.c - part of ruby-oci8
|
4
|
+
|
5
|
+
Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
|
6
|
+
|
7
|
+
*/
|
8
|
+
#include "oci8.h"
|
9
|
+
|
10
|
+
#ifndef DLEXT
|
11
|
+
#define DLEXT ".so"
|
12
|
+
#endif
|
13
|
+
|
14
|
+
/* Exception */
|
15
|
+
VALUE eOCIException;
|
16
|
+
VALUE eOCIBreak;
|
17
|
+
static VALUE eOCINoData;
|
18
|
+
static VALUE eOCIError;
|
19
|
+
static VALUE eOCIInvalidHandle;
|
20
|
+
static VALUE eOCINeedData;
|
21
|
+
static VALUE eOCIStillExecuting;
|
22
|
+
static VALUE eOCIContinue;
|
23
|
+
static VALUE eOCISuccessWithInfo;
|
24
|
+
|
25
|
+
static ID oci8_id_at_code;
|
26
|
+
static ID oci8_id_at_sql;
|
27
|
+
static ID oci8_id_at_parse_error_offset;
|
28
|
+
static ID oci8_id_caller;
|
29
|
+
static ID oci8_id_set_backtrace;
|
30
|
+
|
31
|
+
#define ERRBUF_EXPAND_LEN 256
|
32
|
+
static char *errbuf;
|
33
|
+
static ub4 errbufsiz;
|
34
|
+
|
35
|
+
static OCIMsg *msghp;
|
36
|
+
|
37
|
+
static VALUE set_backtrace(VALUE exc, const char *file, int line);
|
38
|
+
|
39
|
+
static VALUE get_error_msg(dvoid *errhp, ub4 type, const char *default_msg, sb4 *errcode_p)
|
40
|
+
{
|
41
|
+
sword rv;
|
42
|
+
size_t len;
|
43
|
+
|
44
|
+
retry:
|
45
|
+
errbuf[0] = '\0';
|
46
|
+
rv = OCIErrorGet(errhp, 1, NULL, errcode_p, TO_ORATEXT(errbuf), errbufsiz, type);
|
47
|
+
/* OCI manual says:
|
48
|
+
* If type is set to OCI_HTYPE_ERROR, then the return
|
49
|
+
* code during truncation for OCIErrorGet() is
|
50
|
+
* OCI_ERROR. The client can then specify a bigger
|
51
|
+
* buffer and call OCIErrorGet() again.
|
52
|
+
*
|
53
|
+
* But as far as I tested on Oracle XE 10.2.0.1, the return
|
54
|
+
* code is OCI_SUCCESS when the message is truncated.
|
55
|
+
*/
|
56
|
+
len = strlen(errbuf);
|
57
|
+
if (errbufsiz - len <= 7) {
|
58
|
+
/* The error message may be truncated.
|
59
|
+
* The magic number 7 means the maximum length of one utf-8
|
60
|
+
* character plus the length of a nul terminator.
|
61
|
+
*/
|
62
|
+
errbufsiz += ERRBUF_EXPAND_LEN;
|
63
|
+
errbuf = xrealloc(errbuf, errbufsiz);
|
64
|
+
goto retry;
|
65
|
+
}
|
66
|
+
if (rv != OCI_SUCCESS) {
|
67
|
+
/* No message is found. Use the default message. */
|
68
|
+
return rb_usascii_str_new_cstr(default_msg);
|
69
|
+
}
|
70
|
+
|
71
|
+
/* truncate trailing CR and LF */
|
72
|
+
while (len > 0 && (errbuf[len - 1] == '\n' || errbuf[len - 1] == '\r')) {
|
73
|
+
len--;
|
74
|
+
}
|
75
|
+
return rb_external_str_new_with_enc(errbuf, len, oci8_encoding);
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
|
79
|
+
{
|
80
|
+
VALUE exc;
|
81
|
+
char errmsg[128];
|
82
|
+
sb4 errcode = -1;
|
83
|
+
VALUE msg;
|
84
|
+
VALUE parse_error_offset = Qnil;
|
85
|
+
VALUE sql = Qnil;
|
86
|
+
int rv;
|
87
|
+
int numarg = 1;
|
88
|
+
|
89
|
+
switch (status) {
|
90
|
+
case OCI_ERROR:
|
91
|
+
exc = eOCIError;
|
92
|
+
msg = get_error_msg(errhp, type, "Error", &errcode);
|
93
|
+
numarg = 4;
|
94
|
+
break;
|
95
|
+
case OCI_SUCCESS_WITH_INFO:
|
96
|
+
exc = eOCISuccessWithInfo;
|
97
|
+
msg = get_error_msg(errhp, type, "Error", &errcode);
|
98
|
+
numarg = 4;
|
99
|
+
break;
|
100
|
+
case OCI_NO_DATA:
|
101
|
+
exc = eOCINoData;
|
102
|
+
msg = get_error_msg(errhp, type, "No Data", &errcode);
|
103
|
+
numarg = 4;
|
104
|
+
break;
|
105
|
+
case OCI_INVALID_HANDLE:
|
106
|
+
exc = eOCIInvalidHandle;
|
107
|
+
msg = rb_usascii_str_new_cstr("Invalid Handle");
|
108
|
+
break;
|
109
|
+
case OCI_NEED_DATA:
|
110
|
+
exc = eOCINeedData;
|
111
|
+
msg = rb_usascii_str_new_cstr("Need Data");
|
112
|
+
break;
|
113
|
+
case OCI_STILL_EXECUTING:
|
114
|
+
exc = eOCIStillExecuting;
|
115
|
+
msg = rb_usascii_str_new_cstr("Still Executing");
|
116
|
+
break;
|
117
|
+
case OCI_CONTINUE:
|
118
|
+
exc = eOCIContinue;
|
119
|
+
msg = rb_usascii_str_new_cstr("Continue");
|
120
|
+
break;
|
121
|
+
default:
|
122
|
+
sprintf(errmsg, "Unknown error (%d)", status);
|
123
|
+
exc = eOCIException;
|
124
|
+
msg = rb_usascii_str_new_cstr(errmsg);
|
125
|
+
}
|
126
|
+
if (stmthp != NULL) {
|
127
|
+
ub2 offset;
|
128
|
+
text *text;
|
129
|
+
ub4 size;
|
130
|
+
|
131
|
+
rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &offset, 0, OCI_ATTR_PARSE_ERROR_OFFSET, errhp);
|
132
|
+
if (rv == OCI_SUCCESS) {
|
133
|
+
parse_error_offset = INT2FIX(offset);
|
134
|
+
}
|
135
|
+
rv = OCIAttrGet(stmthp, OCI_HTYPE_STMT, &text, &size, OCI_ATTR_STATEMENT, errhp);
|
136
|
+
if (rv == OCI_SUCCESS) {
|
137
|
+
sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
|
138
|
+
}
|
139
|
+
}
|
140
|
+
exc = rb_funcall(exc, oci8_id_new, numarg, msg, INT2FIX(errcode), sql, parse_error_offset);
|
141
|
+
return set_backtrace(exc, file, line);
|
142
|
+
}
|
143
|
+
|
144
|
+
static VALUE set_backtrace(VALUE exc, const char *file, int line)
|
145
|
+
{
|
146
|
+
char errmsg[64];
|
147
|
+
VALUE backtrace;
|
148
|
+
#ifdef _WIN32
|
149
|
+
char *p = strrchr(file, '\\');
|
150
|
+
if (p != NULL)
|
151
|
+
file = p + 1;
|
152
|
+
#endif
|
153
|
+
backtrace = rb_funcall(rb_cObject, oci8_id_caller, 0);
|
154
|
+
if (TYPE(backtrace) == T_ARRAY) {
|
155
|
+
snprintf(errmsg, sizeof(errmsg), "%s:%d:in " STRINGIZE(oci8lib) DLEXT, file, line);
|
156
|
+
errmsg[sizeof(errmsg) - 1] = '\0';
|
157
|
+
rb_ary_unshift(backtrace, rb_usascii_str_new_cstr(errmsg));
|
158
|
+
rb_funcall(exc, oci8_id_set_backtrace, 1, backtrace);
|
159
|
+
}
|
160
|
+
return exc;
|
161
|
+
}
|
162
|
+
|
163
|
+
/*
|
164
|
+
* call-seq:
|
165
|
+
* OCI8.new(message, code = nil, sql = nil, parse_error_offset = nil)
|
166
|
+
*
|
167
|
+
* Creates a new OCIError object.
|
168
|
+
*/
|
169
|
+
static VALUE oci8_error_initialize(int argc, VALUE *argv, VALUE self)
|
170
|
+
{
|
171
|
+
VALUE msg;
|
172
|
+
VALUE code;
|
173
|
+
VALUE sql;
|
174
|
+
VALUE parse_error_offset;
|
175
|
+
|
176
|
+
rb_scan_args(argc, argv, "04", &msg, &code, &sql, &parse_error_offset);
|
177
|
+
rb_call_super(argc > 1 ? 1 : argc, argv);
|
178
|
+
rb_ivar_set(self, oci8_id_at_code, code);
|
179
|
+
rb_ivar_set(self, oci8_id_at_sql, sql);
|
180
|
+
rb_ivar_set(self, oci8_id_at_parse_error_offset, parse_error_offset);
|
181
|
+
return Qnil;
|
182
|
+
}
|
183
|
+
|
184
|
+
sb4 oci8_get_error_code(OCIError *errhp)
|
185
|
+
{
|
186
|
+
sb4 errcode = -1;
|
187
|
+
OCIErrorGet(oci8_errhp, 1, NULL, &errcode, NULL, 0, OCI_HTYPE_ERROR);
|
188
|
+
return errcode;
|
189
|
+
}
|
190
|
+
|
191
|
+
void Init_oci8_error(void)
|
192
|
+
{
|
193
|
+
errbufsiz = ERRBUF_EXPAND_LEN;
|
194
|
+
errbuf = xmalloc(errbufsiz);
|
195
|
+
|
196
|
+
oci8_id_at_code = rb_intern("@code");
|
197
|
+
oci8_id_at_sql = rb_intern("@sql");
|
198
|
+
oci8_id_at_parse_error_offset = rb_intern("@parse_error_offset");
|
199
|
+
oci8_id_caller = rb_intern("caller");
|
200
|
+
oci8_id_set_backtrace = rb_intern("set_backtrace");
|
201
|
+
|
202
|
+
eOCIException = rb_define_class("OCIException", rb_eStandardError);
|
203
|
+
eOCIBreak = rb_define_class("OCIBreak", eOCIException);
|
204
|
+
|
205
|
+
eOCIError = rb_define_class("OCIError", eOCIException);
|
206
|
+
eOCINoData = rb_define_class("OCINoData", eOCIError);
|
207
|
+
eOCIInvalidHandle = rb_define_class("OCIInvalidHandle", eOCIException);
|
208
|
+
eOCINeedData = rb_define_class("OCINeedData", eOCIException);
|
209
|
+
eOCIStillExecuting = rb_define_class("OCIStillExecuting", eOCIException);
|
210
|
+
eOCIContinue = rb_define_class("OCIContinue", eOCIException);
|
211
|
+
eOCISuccessWithInfo = rb_define_class("OCISuccessWithInfo", eOCIError);
|
212
|
+
|
213
|
+
rb_define_method(eOCIError, "initialize", oci8_error_initialize, -1);
|
214
|
+
rb_define_attr(eOCIError, "code", 1, 0);
|
215
|
+
rb_define_attr(eOCIError, "sql", 1, 0);
|
216
|
+
rb_define_attr(eOCIError, "parse_error_offset", 1, 0);
|
217
|
+
rb_define_alias(eOCIError, "parseErrorOffset", "parse_error_offset");
|
218
|
+
}
|
219
|
+
|
220
|
+
void oci8_do_raise(OCIError *errhp, sword status, OCIStmt *stmthp, const char *file, int line)
|
221
|
+
{
|
222
|
+
rb_exc_raise(oci8_make_exc(errhp, status, OCI_HTYPE_ERROR, stmthp, file, line));
|
223
|
+
}
|
224
|
+
|
225
|
+
void oci8_do_env_raise(OCIEnv *envhp, sword status, const char *file, int line)
|
226
|
+
{
|
227
|
+
rb_exc_raise(oci8_make_exc(envhp, status, OCI_HTYPE_ENV, NULL, file, line));
|
228
|
+
}
|
229
|
+
|
230
|
+
void oci8_do_raise_init_error(const char *file, int line)
|
231
|
+
{
|
232
|
+
VALUE msg = rb_usascii_str_new_cstr("OCI Library Initialization Error");
|
233
|
+
VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
|
234
|
+
|
235
|
+
rb_exc_raise(set_backtrace(exc, file, line));
|
236
|
+
}
|
237
|
+
|
238
|
+
VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
|
239
|
+
{
|
240
|
+
char head[32];
|
241
|
+
size_t headsz;
|
242
|
+
const char *errmsg = NULL;
|
243
|
+
char msgbuf[64];
|
244
|
+
|
245
|
+
if (have_OCIMessageGet) {
|
246
|
+
if (msghp == NULL) {
|
247
|
+
chkerr(OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_ORATEXT("rdbms"), TO_ORATEXT("ora"), OCI_DURATION_PROCESS));
|
248
|
+
}
|
249
|
+
errmsg = TO_CHARPTR(OCIMessageGet(msghp, msgno, NULL, 0));
|
250
|
+
}
|
251
|
+
if (errmsg == NULL) {
|
252
|
+
if (default_msg != NULL) {
|
253
|
+
errmsg = default_msg;
|
254
|
+
} else {
|
255
|
+
/* last resort */
|
256
|
+
snprintf(msgbuf, sizeof(msgbuf), "Message %u not found; product=rdbms; facility=ora", msgno);
|
257
|
+
errmsg = msgbuf;
|
258
|
+
}
|
259
|
+
}
|
260
|
+
headsz = snprintf(head, sizeof(head), "ORA-%05u: ", msgno);
|
261
|
+
return rb_str_append(rb_usascii_str_new(head, headsz),
|
262
|
+
rb_external_str_new_with_enc(errmsg, strlen(errmsg), oci8_encoding));
|
263
|
+
}
|
264
|
+
|
265
|
+
void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
|
266
|
+
{
|
267
|
+
VALUE msg = oci8_get_error_message(msgno, default_msg);
|
268
|
+
VALUE exc = rb_funcall(eOCIError, oci8_id_new, 2, msg, INT2FIX(-1));
|
269
|
+
|
270
|
+
rb_exc_raise(set_backtrace(exc, file, line));
|
271
|
+
}
|
272
|
+
|
273
|
+
void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line)
|
274
|
+
{
|
275
|
+
if (status != OCI_SUCCESS) {
|
276
|
+
VALUE exc = oci8_make_exc(oci8_errhp, status, OCI_HTYPE_ERROR, stmthp, file, line);
|
277
|
+
while (base != NULL) {
|
278
|
+
if (base->type == OCI_HTYPE_SVCCTX) {
|
279
|
+
rb_ivar_set(base->self, oci8_id_at_last_error, exc);
|
280
|
+
break;
|
281
|
+
}
|
282
|
+
base = base->parent;
|
283
|
+
}
|
284
|
+
if (status != OCI_SUCCESS_WITH_INFO) {
|
285
|
+
rb_exc_raise(exc);
|
286
|
+
}
|
287
|
+
}
|
288
|
+
}
|
289
|
+
|
290
|
+
/*
|
291
|
+
* Document-class: OCIException
|
292
|
+
*
|
293
|
+
* The superclass for all exceptions raised by ruby-oci8.
|
294
|
+
*
|
295
|
+
* The following exceptions are defined as subclasses of OCIException
|
296
|
+
* These exceptions are raised when Oracle Call Interface functions
|
297
|
+
* return with an error status.
|
298
|
+
*
|
299
|
+
* - OCIBreak
|
300
|
+
* - OCIContinue
|
301
|
+
* - OCIError
|
302
|
+
* - OCISuccessWithInfo
|
303
|
+
* - OCINoData (It had been a subclass of OCIException, not OCIError, until ruby-oci8 2.0)
|
304
|
+
* - OCIInvalidHandle
|
305
|
+
* - OCINeedData
|
306
|
+
* - OCIStillExecuting
|
307
|
+
*/
|
308
|
+
|
309
|
+
/*
|
310
|
+
* Document-class: OCIBreak
|
311
|
+
*
|
312
|
+
* Subclass of OCIException
|
313
|
+
*
|
314
|
+
* Raised when a SQL execution is cancelled by OCI8#break.
|
315
|
+
*/
|
316
|
+
|
317
|
+
/*
|
318
|
+
* Document-class: OCINoData
|
319
|
+
*
|
320
|
+
* Subclass of OCIError from ruby-oci8 2.1.
|
321
|
+
* It had been a subclass of OCIException until ruby-oci8 2.0.
|
322
|
+
*
|
323
|
+
* Raised when PL/SQL NO_DATA_FOUND exception is got.
|
324
|
+
*/
|
325
|
+
|
326
|
+
/*
|
327
|
+
* Document-class: OCIError
|
328
|
+
*
|
329
|
+
* Subclass of OCIException
|
330
|
+
*
|
331
|
+
* The following exceptions are defined as subclasses of OCIError.
|
332
|
+
*
|
333
|
+
* - OCISuccessWithInfo
|
334
|
+
* - OCINoData (It had been a subclass of OCIException, not OCIError, until ruby-oci8 2.0)
|
335
|
+
*
|
336
|
+
* Raised when underlying Oracle Call Interface failed with an Oracle error code
|
337
|
+
* such as ORA-00001.
|
338
|
+
*/
|
339
|
+
|
340
|
+
/*
|
341
|
+
* Document-class: OCIInvalidHandle
|
342
|
+
*
|
343
|
+
* Subclass of OCIException
|
344
|
+
*
|
345
|
+
* Raised when an invalid handle is passed to underlying Oracle Call Interface.
|
346
|
+
* Report to the ruby-oci8 author if it is raised.
|
347
|
+
*/
|
348
|
+
|
349
|
+
/*
|
350
|
+
* Document-class: OCINeedData
|
351
|
+
*
|
352
|
+
* Subclass of OCIException
|
353
|
+
*
|
354
|
+
* Report to the ruby-oci8 author if it is raised.
|
355
|
+
*/
|
356
|
+
|
357
|
+
/*
|
358
|
+
* Document-class: OCIStillExecuting
|
359
|
+
*
|
360
|
+
* Subclass of OCIError
|
361
|
+
*
|
362
|
+
* Report to the ruby-oci8 author if it is raised.
|
363
|
+
*/
|
364
|
+
|
365
|
+
/*
|
366
|
+
* Document-class: OCIContinue
|
367
|
+
*
|
368
|
+
* Subclass of OCIException
|
369
|
+
*
|
370
|
+
* Report to the ruby-oci8 author if it is raised.
|
371
|
+
*/
|
372
|
+
|
373
|
+
/*
|
374
|
+
* Document-class: OCISuccessWithInfo
|
375
|
+
*
|
376
|
+
* Subclass of OCIError
|
377
|
+
*
|
378
|
+
*/
|