ruby-oci8 2.0.3 → 2.0.4
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 +80 -0
- data/NEWS +56 -1
- data/VERSION +1 -1
- data/dist-files +3 -0
- data/ext/oci8/.document +1 -0
- data/ext/oci8/apiwrap.yml +17 -0
- data/ext/oci8/attr.c +1 -1
- data/ext/oci8/bind.c +1 -1
- data/ext/oci8/error.c +91 -2
- data/ext/oci8/extconf.rb +3 -2
- data/ext/oci8/object.c +20 -13
- data/ext/oci8/oci8.c +25 -0
- data/ext/oci8/oci8.h +12 -0
- data/ext/oci8/oci8lib.c +6 -72
- data/ext/oci8/ocidatetime.c +1 -1
- data/ext/oci8/ocihandle.c +702 -0
- data/ext/oci8/ocinumber.c +67 -71
- data/ext/oci8/oradate.c +1 -1
- data/ext/oci8/oranumber_util.c +315 -0
- data/ext/oci8/oranumber_util.h +24 -0
- data/ext/oci8/stmt.c +11 -9
- data/lib/oci8/datetime.rb +5 -1
- data/test/test_oranumber.rb +144 -1
- metadata +23 -7
data/ChangeLog
CHANGED
@@ -1,3 +1,83 @@
|
|
1
|
+
2010-02-28 KUBO Takehiro <kubo@jiubao.org>
|
2
|
+
* NEWS: add changes between 2.0.3 and 2.0.4.
|
3
|
+
* VERSION: change the version to 2.0.3.
|
4
|
+
* ext/oci8/stmt.c: fix segmentation fault when OCI8::Cursor#fetch
|
5
|
+
is called prior to OCI8::Cursor#exec.
|
6
|
+
* ext/oci8/oci8.c: minor fix in rdoc comment.
|
7
|
+
|
8
|
+
2010-02-27 KUBO Takehiro <kubo@jiubao.org>
|
9
|
+
* lib/oci8/datetime.rb: fix a problem that fractional seconds are lost
|
10
|
+
when Time value is bound to TIMESTAMP.
|
11
|
+
(reported by Raimonds Simanovskis)
|
12
|
+
|
13
|
+
2010-02-27 KUBO Takehiro <kubo@jiubao.org>
|
14
|
+
* ext/oci8/error.c, ext/oci8/extconf.rb, ext/oci8/oci8.h: fix for
|
15
|
+
old Oracle versions, which lack declarations of OCIMsg, oraub8,
|
16
|
+
orasb8 and OCI_DURATION_PROCESS.
|
17
|
+
* ext/oci8/ocihandle.c: fix for mingw compiler.
|
18
|
+
|
19
|
+
2010-02-27 KUBO Takehiro <kubo@jiubao.org>
|
20
|
+
* ext/oci8/apiwrap.yml, ext/oci8/error.c, ext/oci8/oci8.h,
|
21
|
+
ext/oci8/ocinumber.c: fix for Oracle 8.0 client, which doesn't
|
22
|
+
have OCIMessageOpen() and OCIMessageGet().
|
23
|
+
* ext/oci8/oci8.c: add a new method OCI8.error_message to get
|
24
|
+
a error message which depends on NLS_LANGUAGE.
|
25
|
+
|
26
|
+
2010-02-09 KUBO Takehiro <kubo@jiubao.org>
|
27
|
+
* dist-files: add ext/oci8/oranumber_util.c and
|
28
|
+
ext/oci8/oranumber_util.h.
|
29
|
+
(reported by Raimonds Simanovskis)
|
30
|
+
|
31
|
+
2010-02-07 KUBO Takehiro <kubo@jiubao.org>
|
32
|
+
* ext/oci8/ocinumber.c, ext/oci8/oranumber_util.c,
|
33
|
+
ext/oci8/oranumber_util.h: change the declaration of
|
34
|
+
oranumber_to_str() to prevent buffer overflow by
|
35
|
+
unexpected invalid Oracle number internal data.
|
36
|
+
|
37
|
+
2010-02-07 KUBO Takehiro <kubo@jiubao.org>
|
38
|
+
* ext/oci8/error.c, ext/oci8/oci8.h: add oci8_raise_by_msgno()
|
39
|
+
to retrieve a Oracle error message which depends on NLS_LANGUAGE.
|
40
|
+
* ext/oci8/oranumber_util.c, ext/oci8/oranumber_util.h,
|
41
|
+
ext/oci8/extconf.rb: add handwritten conversion functions from
|
42
|
+
OCINumber internal representation to string and vice versa.
|
43
|
+
* ext/oci8/ocinumber.c: 1. use handwritten conversion functions
|
44
|
+
instead of OCI functions to convert OraNumber to string
|
45
|
+
and vice varse. 2. add OraNumber#dump.
|
46
|
+
* test/test_oranumber.rb: add test cases to check conversion from
|
47
|
+
OraNumber to string and vice varse.
|
48
|
+
|
49
|
+
2010-02-02 KUBO Takehiro <kubo@jiubao.org>
|
50
|
+
* ext/oci8/ocinumber.c: fix to support NUMBERS with scale larger
|
51
|
+
than 38 by using scientific number notation to convert OraNumber
|
52
|
+
to BigDecimal. OraNumber#to_i is also fixed.
|
53
|
+
(reported by Raimonds Simanovskis)
|
54
|
+
|
55
|
+
2010-01-24 KUBO Takehiro <kubo@jiubao.org>
|
56
|
+
* ext/oci8/error.c: Use OCIErrorGet() to retrieve the error message
|
57
|
+
when the OCI return code is OCI_NO_DATA.
|
58
|
+
(reported by Raimonds Simanovskis)
|
59
|
+
|
60
|
+
2009-12-06 KUBO Takehiro <kubo@jiubao.org>
|
61
|
+
* ext/oci8/object.c: 1. fix segv when GC starts while initializing
|
62
|
+
a bind object for object type. (reported by Remi Gagnon)
|
63
|
+
2. fix memory leak about 30 bytes per one bind object for object
|
64
|
+
type.
|
65
|
+
|
66
|
+
2009-11-03 KUBO Takehiro <kubo@jiubao.org>
|
67
|
+
* ext/oci8/object.c: fix segv when binding a collection of string.
|
68
|
+
(reported by Raimonds Simanovskis)
|
69
|
+
|
70
|
+
2009-10-26 KUBO Takehiro <kubo@jiubao.org>
|
71
|
+
* NEW: fix typo.
|
72
|
+
* dist-files, ext/oci8/.document: add ocihandle.c.
|
73
|
+
* ext/oci8/ocihandle.c: add private methods OCIHandle#attr_get_*,
|
74
|
+
OCIHandle#attr_set_* and their rdoc comments.
|
75
|
+
|
76
|
+
2009-10-23 KUBO Takehiro <kubo@jiubao.org>
|
77
|
+
* ext/oci8/extconf.rb, ext/oci8/oci8.h, ext/oci8/oci8lib.c,
|
78
|
+
ext/oci8/ocihandle.c: add ocihandle.c and move OCIHandle
|
79
|
+
definitions from oci8lib.c to the file.
|
80
|
+
|
1
81
|
2009-10-21 KUBO Takehiro <kubo@jiubao.org>
|
2
82
|
* NEWS: add changes between 2.0.2 and 2.0.3.
|
3
83
|
* VERSION, Makefile: change the version to 2.0.3.
|
data/NEWS
CHANGED
@@ -1,6 +1,61 @@
|
|
1
|
+
2.0.4:
|
2
|
+
|
3
|
+
* New Features
|
4
|
+
|
5
|
+
- OCI8.error_message(message_no) -> string
|
6
|
+
|
7
|
+
Gets the Oracle error message specified by message id.
|
8
|
+
Its language depends on NLS_LANGUAGE.
|
9
|
+
|
10
|
+
Note: This method is unavailable if the Oracle client
|
11
|
+
version is 8.0.
|
12
|
+
|
13
|
+
# When NLS_LANG is AMERICAN_AMERICA.AL32UTF8
|
14
|
+
OCI8.error_message(1)
|
15
|
+
# => "ORA-00001: unique constraint (%s.%s) violated"
|
16
|
+
|
17
|
+
# When NLS_LANG is FRENCH_FRANCE.AL32UTF8
|
18
|
+
OCI8.error_message(1)
|
19
|
+
# => "ORA-00001: violation de contrainte unique (%s.%s)"
|
20
|
+
|
21
|
+
- OraNumber#dump -> string
|
22
|
+
|
23
|
+
Returns OraNumber's internal representation whose format
|
24
|
+
is same with the return value of Oracle SQL function DUMP().
|
25
|
+
|
26
|
+
OraNumber.new(100).dump #=> "Typ=2 Len=2: 194,2"
|
27
|
+
OraNumber.new(123).dump #=> "Typ=2 Len=3: 194,2,24"
|
28
|
+
OraNumber.new(0.1).dump #=> "Typ=2 Len=2: 192,11"
|
29
|
+
|
30
|
+
* Fixed issues
|
31
|
+
|
32
|
+
- Fractional second part is lost when ruby's Time instance is bound
|
33
|
+
to Oracle datatype TIMESTAMP.
|
34
|
+
(reported by Raimonds Simanovskis)
|
35
|
+
|
36
|
+
- OraNumber#to_i and OraNumber#to_s fail when its scale is larger
|
37
|
+
than 38.
|
38
|
+
(reported by Raimonds Simanovskis)
|
39
|
+
|
40
|
+
- Memory leak about 30 bytes per one place holder for object type.
|
41
|
+
|
42
|
+
- Segmentation fault when a collection of string is bound.
|
43
|
+
(reported by Raimonds Simanovskis)
|
44
|
+
|
45
|
+
- Segmentation fault when GC starts while initializing a bind
|
46
|
+
object for object type.
|
47
|
+
(reported by Remi Gagnon)
|
48
|
+
|
49
|
+
- Segmentation fault when OCI8::Cursor#fetch is called prior to
|
50
|
+
OCI8::Cursor#exec.
|
51
|
+
|
52
|
+
- Detailed error message is not reported when PL/SQL NO_DATA_FOUND
|
53
|
+
exception is raised.
|
54
|
+
(reported by Raimonds Simanovskis)
|
55
|
+
|
1
56
|
2.0.3:
|
2
57
|
|
3
|
-
*
|
58
|
+
* Incompatible Changes
|
4
59
|
|
5
60
|
- Number column in a SQL statement
|
6
61
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.0.
|
1
|
+
2.0.4
|
data/dist-files
CHANGED
@@ -31,9 +31,12 @@ ext/oci8/oci8.c
|
|
31
31
|
ext/oci8/oci8.h
|
32
32
|
ext/oci8/oci8lib.c
|
33
33
|
ext/oci8/ocidatetime.c
|
34
|
+
ext/oci8/ocihandle.c
|
34
35
|
ext/oci8/ocinumber.c
|
35
36
|
ext/oci8/oraconf.rb
|
36
37
|
ext/oci8/oradate.c
|
38
|
+
ext/oci8/oranumber_util.c
|
39
|
+
ext/oci8/oranumber_util.h
|
37
40
|
ext/oci8/post-config.rb
|
38
41
|
ext/oci8/stmt.c
|
39
42
|
ext/oci8/object.c
|
data/ext/oci8/.document
CHANGED
data/ext/oci8/apiwrap.yml
CHANGED
@@ -947,6 +947,23 @@ OCILobOpen_nb:
|
|
947
947
|
- OCILobLocator *locp
|
948
948
|
- ub1 mode
|
949
949
|
|
950
|
+
OCIMessageOpen:
|
951
|
+
:version: 810
|
952
|
+
:args: - dvoid *envhp
|
953
|
+
- OCIError *errhp
|
954
|
+
- OCIMsg **msghp
|
955
|
+
- CONST OraText *product
|
956
|
+
- CONST OraText *facility
|
957
|
+
- OCIDuration dur
|
958
|
+
|
959
|
+
OCIMessageGet:
|
960
|
+
:version: 810
|
961
|
+
:ret: OraText *
|
962
|
+
:args: - OCIMsg *msgh
|
963
|
+
- ub4 msgno
|
964
|
+
- OraText *msgbuf
|
965
|
+
- size_t buflen
|
966
|
+
|
950
967
|
# round trip: 0
|
951
968
|
OCINumberIsInt:
|
952
969
|
:version: 810
|
data/ext/oci8/attr.c
CHANGED
data/ext/oci8/bind.c
CHANGED
data/ext/oci8/error.c
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
/*
|
3
3
|
error.c - part of ruby-oci8
|
4
4
|
|
5
|
-
Copyright (C) 2002-
|
5
|
+
Copyright (C) 2002-2010 KUBO Takehiro <kubo@jiubao.org>
|
6
6
|
|
7
7
|
=begin
|
8
8
|
== OCIError
|
@@ -28,9 +28,58 @@ static ID oci8_id_sql;
|
|
28
28
|
static ID oci8_id_caller;
|
29
29
|
static ID oci8_id_set_backtrace;
|
30
30
|
|
31
|
+
#define ERRBUF_EXPAND_LEN 256
|
32
|
+
static char *errbuf;
|
33
|
+
static ub4 errbufsiz;
|
34
|
+
|
35
|
+
static OCIMsg *msghp;
|
36
|
+
|
37
|
+
#ifndef OCI_DURATION_PROCESS
|
38
|
+
#define OCI_DURATION_PROCESS ((OCIDuration)5)
|
39
|
+
#endif
|
40
|
+
|
31
41
|
NORETURN(static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line));
|
32
42
|
NORETURN(static void set_backtrace_and_raise(VALUE exc, const char *file, int line));
|
33
43
|
|
44
|
+
static VALUE get_error_msg(dvoid *errhp, ub4 type, const char *default_msg, sb4 *errcode_p)
|
45
|
+
{
|
46
|
+
sword rv;
|
47
|
+
size_t len;
|
48
|
+
|
49
|
+
retry:
|
50
|
+
errbuf[0] = '\0';
|
51
|
+
rv = OCIErrorGet(errhp, 1, NULL, errcode_p, TO_ORATEXT(errbuf), errbufsiz, type);
|
52
|
+
/* OCI manual says:
|
53
|
+
* If type is set to OCI_HTYPE_ERROR, then the return
|
54
|
+
* code during truncation for OCIErrorGet() is
|
55
|
+
* OCI_ERROR. The client can then specify a bigger
|
56
|
+
* buffer and call OCIErrorGet() again.
|
57
|
+
*
|
58
|
+
* But as far as I tested on Oracle XE 10.2.0.1, the return
|
59
|
+
* code is OCI_SUCCESS when the message is truncated.
|
60
|
+
*/
|
61
|
+
len = strlen(errbuf);
|
62
|
+
if (errbufsiz - len <= 7) {
|
63
|
+
/* The error message may be truncated.
|
64
|
+
* The magic number 7 means the maximum length of one utf-8
|
65
|
+
* character plus the length of a nul terminator.
|
66
|
+
*/
|
67
|
+
errbufsiz += ERRBUF_EXPAND_LEN;
|
68
|
+
errbuf = xrealloc(errbuf, errbufsiz);
|
69
|
+
goto retry;
|
70
|
+
}
|
71
|
+
if (rv != OCI_SUCCESS) {
|
72
|
+
/* No message is found. Use the default message. */
|
73
|
+
return rb_usascii_str_new_cstr(default_msg);
|
74
|
+
}
|
75
|
+
|
76
|
+
/* truncate trailing CR and LF */
|
77
|
+
while (len > 0 && (errbuf[len - 1] == '\n' || errbuf[len - 1] == '\r')) {
|
78
|
+
len--;
|
79
|
+
}
|
80
|
+
return rb_external_str_new_with_enc(errbuf, len, oci8_encoding);
|
81
|
+
}
|
82
|
+
|
34
83
|
static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
|
35
84
|
{
|
36
85
|
VALUE vcodes = Qnil;
|
@@ -103,7 +152,7 @@ static void oci8_raise2(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, c
|
|
103
152
|
break;
|
104
153
|
case OCI_NO_DATA:
|
105
154
|
exc = eOCINoData;
|
106
|
-
msg =
|
155
|
+
msg = get_error_msg(errhp, type, "No Data", &errcode);
|
107
156
|
break;
|
108
157
|
case OCI_INVALID_HANDLE:
|
109
158
|
exc = eOCIInvalidHandle;
|
@@ -252,6 +301,9 @@ sb4 oci8_get_error_code(OCIError *errhp)
|
|
252
301
|
|
253
302
|
void Init_oci8_error(void)
|
254
303
|
{
|
304
|
+
errbufsiz = ERRBUF_EXPAND_LEN;
|
305
|
+
errbuf = xmalloc(errbufsiz);
|
306
|
+
|
255
307
|
oci8_id_code = rb_intern("code");
|
256
308
|
oci8_id_message = rb_intern("message");
|
257
309
|
oci8_id_parse_error_offset = rb_intern("parse_error_offset");
|
@@ -301,3 +353,40 @@ void oci8_do_raise_init_error(const char *file, int line)
|
|
301
353
|
rb_ivar_set(exc, oci8_id_message, rb_ary_new3(1, msg));
|
302
354
|
set_backtrace_and_raise(exc, file, line);
|
303
355
|
}
|
356
|
+
|
357
|
+
VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
|
358
|
+
{
|
359
|
+
char head[32];
|
360
|
+
size_t headsz;
|
361
|
+
const char *errmsg = NULL;
|
362
|
+
char msgbuf[64];
|
363
|
+
|
364
|
+
if (have_OCIMessageGet) {
|
365
|
+
if (msghp == NULL) {
|
366
|
+
oci_lc(OCIMessageOpen(oci8_envhp, oci8_errhp, &msghp, TO_ORATEXT("rdbms"), TO_ORATEXT("ora"), OCI_DURATION_PROCESS));
|
367
|
+
}
|
368
|
+
errmsg = TO_CHARPTR(OCIMessageGet(msghp, msgno, NULL, 0));
|
369
|
+
}
|
370
|
+
if (errmsg == NULL) {
|
371
|
+
if (default_msg != NULL) {
|
372
|
+
errmsg = default_msg;
|
373
|
+
} else {
|
374
|
+
/* last resort */
|
375
|
+
snprintf(msgbuf, sizeof(msgbuf), "Message %u not found; product=rdbms; facility=ora", msgno);
|
376
|
+
errmsg = msgbuf;
|
377
|
+
}
|
378
|
+
}
|
379
|
+
headsz = snprintf(head, sizeof(head), "ORA-%05u: ", msgno);
|
380
|
+
return rb_str_append(rb_usascii_str_new(head, headsz),
|
381
|
+
rb_external_str_new_with_enc(errmsg, strlen(errmsg), oci8_encoding));
|
382
|
+
}
|
383
|
+
|
384
|
+
void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
|
385
|
+
{
|
386
|
+
VALUE msg = oci8_get_error_message(msgno, default_msg);
|
387
|
+
VALUE exc = rb_funcall(eOCIError, oci8_id_new, 1, msg);
|
388
|
+
|
389
|
+
rb_ivar_set(exc, oci8_id_code, rb_ary_new3(1, INT2FIX(-1)));
|
390
|
+
rb_ivar_set(exc, oci8_id_message, rb_ary_new3(1, msg));
|
391
|
+
set_backtrace_and_raise(exc, file, line);
|
392
|
+
}
|
data/ext/oci8/extconf.rb
CHANGED
@@ -69,6 +69,7 @@ have_type('OCIInterval*', 'ociap.h')
|
|
69
69
|
have_type('OCICallbackLobRead2', 'ociap.h')
|
70
70
|
have_type('OCICallbackLobWrite2', 'ociap.h')
|
71
71
|
have_type('OCIAdmin*', 'ociap.h')
|
72
|
+
have_type('OCIMsg*', 'ociap.h')
|
72
73
|
|
73
74
|
if with_config('oracle-version')
|
74
75
|
oci_client_version = OCI8::OracleVersion.new(with_config('oracle-version')).to_i
|
@@ -82,11 +83,11 @@ if with_config('runtime-check')
|
|
82
83
|
$libs = saved_libs
|
83
84
|
end
|
84
85
|
|
85
|
-
$objs = ["oci8lib.o", "env.o", "error.o", "oci8.o",
|
86
|
+
$objs = ["oci8lib.o", "env.o", "error.o", "oci8.o", "ocihandle.o",
|
86
87
|
"stmt.o", "bind.o", "metadata.o", "attr.o",
|
87
88
|
"lob.o", "oradate.o",
|
88
89
|
"ocinumber.o", "ocidatetime.o", "object.o", "apiwrap.o",
|
89
|
-
"encoding.o", "xmldb.o"]
|
90
|
+
"encoding.o", "xmldb.o", "oranumber_util.o"]
|
90
91
|
|
91
92
|
if RUBY_PLATFORM =~ /mswin32|cygwin|mingw32|bccwin32/
|
92
93
|
$defs << "-DUSE_WIN32_C"
|
data/ext/oci8/object.c
CHANGED
@@ -300,11 +300,11 @@ static VALUE oci8_named_coll_set_coll_element(VALUE self, VALUE datatype, VALUE
|
|
300
300
|
switch (FIX2INT(datatype)) {
|
301
301
|
case ATTR_STRING:
|
302
302
|
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_VARCHAR2, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
303
|
-
|
303
|
+
cb_data.indp = &cb_data.ind;
|
304
304
|
break;
|
305
305
|
case ATTR_RAW:
|
306
306
|
oci_lc(OCIObjectNew(oci8_envhp, oci8_errhp, svcctx->hp.svc, OCI_TYPECODE_RAW, NULL, NULL, OCI_DURATION_SESSION, TRUE, &cb_data.data.ptr));
|
307
|
-
|
307
|
+
cb_data.indp = &cb_data.ind;
|
308
308
|
break;
|
309
309
|
case ATTR_OCINUMBER:
|
310
310
|
case ATTR_FLOAT:
|
@@ -498,11 +498,14 @@ static void bind_named_type_mark(oci8_base_t *base)
|
|
498
498
|
{
|
499
499
|
oci8_bind_t *obind = (oci8_bind_t *)base;
|
500
500
|
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
501
|
-
ub4 idx = 0;
|
502
501
|
|
503
|
-
|
504
|
-
|
505
|
-
|
502
|
+
if (oho != NULL) {
|
503
|
+
ub4 idx = 0;
|
504
|
+
|
505
|
+
do {
|
506
|
+
rb_gc_mark(oho[idx].obj);
|
507
|
+
} while (++idx < obind->maxar_sz);
|
508
|
+
}
|
506
509
|
rb_gc_mark(obind->tdo);
|
507
510
|
}
|
508
511
|
|
@@ -510,14 +513,18 @@ static void bind_named_type_free(oci8_base_t *base)
|
|
510
513
|
{
|
511
514
|
oci8_bind_t *obind = (oci8_bind_t *)base;
|
512
515
|
oci8_hp_obj_t *oho = (oci8_hp_obj_t *)obind->valuep;
|
513
|
-
ub4 idx = 0;
|
514
516
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
517
|
+
if (oho != NULL) {
|
518
|
+
ub4 idx = 0;
|
519
|
+
|
520
|
+
do {
|
521
|
+
if (oho[idx].hp != NULL) {
|
522
|
+
OCIObjectFree(oci8_envhp, oci8_errhp, oho[idx].hp, OCI_DEFAULT);
|
523
|
+
oho[idx].hp = NULL;
|
524
|
+
}
|
525
|
+
} while (++idx < obind->maxar_sz);
|
526
|
+
}
|
527
|
+
oci8_bind_free(base);
|
521
528
|
}
|
522
529
|
|
523
530
|
static VALUE bind_named_type_get(oci8_bind_t *obind, void *data, void *null_struct)
|
data/ext/oci8/oci8.c
CHANGED
@@ -64,6 +64,28 @@ static VALUE oci8_s_oracle_client_vernum(VALUE klass)
|
|
64
64
|
return oracle_client_vernum;
|
65
65
|
}
|
66
66
|
|
67
|
+
/*
|
68
|
+
* call-seq:
|
69
|
+
* OCI8.error_message(message_no) -> string
|
70
|
+
*
|
71
|
+
* Get the Oracle error message specified by message_no.
|
72
|
+
* Its language depends on NLS_LANGUAGE.
|
73
|
+
*
|
74
|
+
* Note: This method is unavailable if the Oracle client version is 8.0.
|
75
|
+
*
|
76
|
+
* example:
|
77
|
+
* # When NLS_LANG is AMERICAN_AMERICA.AL32UTF8
|
78
|
+
* OCI8.error_message(1) # => "ORA-00001: unique constraint (%s.%s) violated"
|
79
|
+
*
|
80
|
+
* # When NLS_LANG is FRENCH_FRANCE.AL32UTF8
|
81
|
+
* OCI8.error_message(1) # => "ORA-00001: violation de contrainte unique (%s.%s)"
|
82
|
+
*
|
83
|
+
*/
|
84
|
+
static VALUE oci8_s_error_message(VALUE klass, VALUE msgid)
|
85
|
+
{
|
86
|
+
return oci8_get_error_message(NUM2UINT(msgid), NULL);
|
87
|
+
}
|
88
|
+
|
67
89
|
#define CONN_STR_REGEX "/^([^(\\s|\\@)]*)\\/([^(\\s|\\@)]*)(?:\\@(\\S+))?(?:\\s+as\\s+(\\S*)\\s*)?$/i"
|
68
90
|
static void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALUE *dbname, VALUE *mode)
|
69
91
|
{
|
@@ -942,6 +964,9 @@ VALUE Init_oci8(void)
|
|
942
964
|
id_set_prefetch_rows = rb_intern("prefetch_rows=");
|
943
965
|
|
944
966
|
rb_define_singleton_method_nodoc(cOCI8, "oracle_client_vernum", oci8_s_oracle_client_vernum, 0);
|
967
|
+
if (have_OCIMessageOpen && have_OCIMessageGet) {
|
968
|
+
rb_define_singleton_method(cOCI8, "error_message", oci8_s_error_message, 1);
|
969
|
+
}
|
945
970
|
rb_define_private_method(cOCI8, "parse_connect_string", oci8_parse_connect_string, 1);
|
946
971
|
rb_define_method(cOCI8, "initialize", oci8_svcctx_initialize, -1);
|
947
972
|
rb_define_method(cOCI8, "logoff", oci8_svcctx_logoff, 0);
|