ruby-oci8 2.0.3 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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);
|