ruby-oci8 2.2.4.1 → 2.2.5

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,7 +1,57 @@
1
+ 2017-10-21 Kubo Takehiro <kubo@jiubao.org>
2
+ * NEWS: Add changes between 2.2.4.1 and 2.2.5
3
+ * lib/oci8/version.rb: Update to 2.2.5
4
+ * docs/number-type-mapping.md: minor fix
5
+ * dist-files: Add files.
6
+
7
+ 2017-10-18 Kubo Takehiro <kubo@jiubao.org>
8
+ * docs/number-type-mapping.md, README.md, dist-files: Add document
9
+ about the mapping between Oracle number types and Ruby classes.
10
+
11
+ 2017-10-17 Kubo Takehiro <kubo@jiubao.org>
12
+ * lib/oci8/check_load_error.rb: Check error reason when loading
13
+ failed with 'The specified module could not be found' on Windows.
14
+
15
+ 2017-10-17 Kubo Takehiro <kubo@jiubao.org>
16
+ * lib/oci8/check_load_error.rb: Fix LoadError while trying to check
17
+ errors in "require 'oci8lib_230.so'" on cygwin 2.8 or later.
18
+ (related to github issue #176)
19
+
20
+ 2017-10-17 Kubo Takehiro <kubo@jiubao.org>
21
+ * ext/oci8/ocinumber.c, test/test_oranumber.rb:
22
+ Add OraNumber#has_fractional_part?.
23
+
24
+ 2017-10-01 Kubo Takehiro <kubo@jiubao.org>
25
+ * ext/oci8/plthook_elf.c: Update plthook to use prelinked
26
+ libclntsh.so on Linux.
27
+ (github issue #172)
28
+
29
+ 2017-09-27 Kubo Takehiro <kubo@jiubao.org>
30
+ * ext/oci8/oci8lib.c: Change order to load libclntsh when runtime
31
+ api check is enabled on Unix.
32
+
33
+ 2017-09-24 Kubo Takehiro <kubo@jiubao.org>
34
+ * ext/oci8/oci8lib.c: Try to load $ORACLE_HOME/lib/libclntsh.so also
35
+ when runtime api check is enabled on Unix.
36
+
37
+ 2017-09-23 Kubo Takehiro <kubo@jiubao.org>
38
+ * lib/oci8/cursor.rb: Don't call unnecessary __paramGet(i) when a
39
+ cursor is executed more than once.
40
+ (pointed by OMOTO Kenji at github issue #171)
41
+
42
+ 2017-07-09 Kubo Takehiro <kubo@jiubao.org>
43
+ * ext/oci8/apiwrap.yml, ext/oci8/oci8.c, lib/oci8/oci8.rb:
44
+ Delete unused code using OCILogon2 and OCILogoff.
45
+
46
+ 2017-07-09 Kubo Takehiro <kubo@jiubao.org>
47
+ * ext/oci8/error.c: Delete OCIError#initialize defined by C code
48
+ to suppress warning: method redefined; discarding old initialize.
49
+ (github issue #168)
50
+
1
51
  2017-06-17 Kubo Takehiro <kubo@jiubao.org>
2
52
  * NEWS: Add changes between 2.2.4 and 2.2.4.1
3
53
  * lib/oci8/version.rb: Update to 2.2.4.1
4
- * lib/oci8/version.rb: Fix URL links
54
+ * lib/oci8/properties.rb: Fix URL links
5
55
  * docs/hanging-after-inactivity.md: Revised
6
56
 
7
57
  2017-06-16 Kubo Takehiro <kubo@jiubao.org>
data/NEWS CHANGED
@@ -1,5 +1,63 @@
1
1
  # @markup markdown
2
2
 
3
+ 2.2.5
4
+ =====
5
+
6
+ New Features
7
+ ------------
8
+
9
+ ### Try to load $ORACLE_HOME/lib/libclntsh.so also when runtime api check is enabled on Unix.
10
+
11
+ When ruby-oci8 is configured with `--with-runtime-check`, it loads Oracle client
12
+ library and checks available functions in the library at runtime. This feature was
13
+ added to release Windows binary gems which cannot know Oracle version at compile time.
14
+ This is available also on Unix. However it tries to load libraries in LD_LIBRARY_PATH only.
15
+ From this version, it tries to load $ORACLE_HOME/lib/libclntsh.so also.
16
+
17
+ ### Check error reasons when loading failed with 'The specified module could not be found' on Windows.
18
+
19
+ The error messages are same when OCI.DLL isn't found and when Visual
20
+ C++ runtime library depended on by OCI.DLL isn't found. From this
21
+ version, ruby-oci8 distinguishes the difference and prints other message
22
+ for the latter case.
23
+
24
+ Fixed issue
25
+ -----------
26
+
27
+ ### Fix segmentation fault when Oracle client library is prelinked.
28
+
29
+ When Oracle instant client rpm package is used on RHEL5 or RHEL6,
30
+ Oracle client library is modified by [prelink][] and ruby-oci8 crashed
31
+ with segmentation fault. This is not due to Oracle, but due to
32
+ plthook used by ruby-oci8. The plthook was fixed to work with
33
+ prelinked libraries.
34
+ (github issue #172)
35
+
36
+ [prelink]: https://en.wikipedia.org/wiki/Prelink#Linux
37
+
38
+ ### Fix not to hide the original error message of LoadError on recent cygwin.
39
+
40
+ Ruby-oci8 tries to check error messages when `require 'oci8lib_xxx.so` fails.
41
+ However the message was hidden by an exception while checking on cygwin.
42
+ (github issue #176)
43
+
44
+ ### Don't call unnecessary __paramGet(i) when a cursor is executed more than once.
45
+
46
+ pointed by OMOTO Kenji
47
+ (github issue #171)
48
+
49
+ ### Suppress warning: method redefined; discarding old initialize.
50
+
51
+ (github issue #168)
52
+
53
+ Other Changes
54
+ -------------
55
+
56
+ ### Add document about the mapping between Oracle number types and Ruby classes.
57
+
58
+ See {file:docs/number-type-mapping.md Number Type Mapping between Oracle and Ruby}.
59
+ (github issue #173)
60
+
3
61
  2.2.4.1
4
62
  =======
5
63
 
data/README.md CHANGED
@@ -24,7 +24,9 @@ See {file:NEWS}.
24
24
  Sample one-liner
25
25
  ----------------
26
26
 
27
- Connect to scott/tiger, select `emp` and print as CSV format.
27
+ When you have an Oracle database server to which `sqlplus scott/tiger` can connect
28
+ and `scott` user has `emp` table, you can select `emp` and print rows
29
+ as CSV by the followig one liner.
28
30
 
29
31
  ruby -r oci8 -e "OCI8.new('scott', 'tiger').exec('select * from emp') do |r| puts r.join(','); end"
30
32
 
@@ -50,6 +52,7 @@ Report issues
50
52
  Other documents
51
53
  ---------------
52
54
 
55
+ * {file:docs/number-type-mapping.md Number Type Mapping between Oracle and Ruby}
53
56
  * {file:docs/timeout-parameters.md Timeout Parameters}
54
57
  * {file:docs/conflicts-local-connections-and-processes.md Conflicts between Local Connections and Child Process Handling on Unix}
55
58
  * {file:docs/hanging-after-inactivity.md Hanging After a Long Period of Inactivity}
data/dist-files CHANGED
@@ -11,12 +11,14 @@ pre-distclean.rb
11
11
  ruby-oci8.gemspec
12
12
  setup.rb
13
13
  docs/bind-array-to-in_cond.md
14
+ docs/conflicts-local-connections-and-processes.md
15
+ docs/hanging-after-inactivity.md
14
16
  docs/install-binary-package.md
15
17
  docs/install-full-client.md
16
18
  docs/install-instant-client.md
17
19
  docs/install-on-osx.md
18
- docs/conflicts-local-connections-and-processes.md
19
- docs/hanging-after-inactivity.md
20
+ docs/ldap-auth-and-function-interposition.md
21
+ docs/number-type-mapping.md
20
22
  docs/osx-install-dev-tools.png
21
23
  docs/platform-specific-issues.md
22
24
  docs/report-installation-issue.md
@@ -81,10 +83,12 @@ lib/ruby-oci8.rb
81
83
  test/README
82
84
  test/config.rb
83
85
  test/setup_test_object.sql
86
+ test/setup_test_package.sql
84
87
  test/test_all.rb
85
88
  test/test_appinfo.rb
86
89
  test/test_array_dml.rb
87
90
  test/test_bind_array.rb
91
+ test/test_bind_boolean.rb
88
92
  test/test_bind_raw.rb
89
93
  test/test_bind_string.rb
90
94
  test/test_bind_time.rb
@@ -27,7 +27,7 @@ The above code is rewritten as follows:
27
27
 
28
28
  ids = [ ... ] # an arbitrary-length array containing user IDs.
29
29
 
30
- in_cond = OCI8::in_cond(:id, ids)]
30
+ in_cond = OCI8::in_cond(:id, ids)
31
31
  cursor = conn.exec("select * from users where id in (#{in_cond.names})", *in_cond.values)
32
32
 
33
33
  or
@@ -0,0 +1,123 @@
1
+ # @title LDAP Authentication and Function Interposition
2
+
3
+ LDAP Authentication and Function Interposition
4
+ ==============================================
5
+
6
+ Problems
7
+ --------
8
+
9
+ The following code may trigger segmentation faults or unexpected behaviours.
10
+
11
+ require 'pg' # or any modules using LDAP such as ActiveLdap
12
+ require 'oci8'
13
+
14
+ conn = OCI8.new('username/password@dbname.example.com')
15
+ ...
16
+
17
+ It happens when all the following conditions are satisfied.
18
+
19
+ * The platform is Unix
20
+ * The PostgreSQL client library, which `pg` depends, was compiled with LDAP support.
21
+ * LDAP authentication is used to connect to an Oracle server.
22
+
23
+ It is caused by function interposition as follows:
24
+
25
+ * The ruby process loads `pq` and its depending libraries such as
26
+ `libpq.so`(PostgreSQL client library) and `libldap_r.so`(LDAP library).
27
+ * Then it loads `oci8` and its depending libraries such as
28
+ `libclntsh.so`(Oracle client library).
29
+ * When LDAP authentication is used, `libclntsh.so` tries to use
30
+ LDAP functions in the library.
31
+ * However it uses LDAP functions in `libldap_r.so` because the function
32
+ in the firstly loaded library is used when more than one library exports
33
+ functions whose names are same.
34
+ * It triggers segmentation faults or unexpected behaviours because
35
+ implementations of LDAP functions are different even though their names
36
+ are same.
37
+
38
+ The reverse may cause same results by the following code.
39
+
40
+ require 'oci8'
41
+ require 'pg'
42
+
43
+ ... connect to PostgreSQL using LDAP ...
44
+
45
+ ### Note for macOS
46
+
47
+ Libraries in two-level namespaces are free from function interposition on macOS.
48
+ See the second paragraph of [this document][mach-o]. If `TWOLEVEL` is
49
+ found in the output of `otool -hV /path/to/library`, it is in a
50
+ two-level namespace. Otherwise it is in a single-level (flat) namespace.
51
+
52
+ Oracle client library (`libclntsh.dylib.12.1`) is in a flat namespace.
53
+ It suffers from function interposition.
54
+
55
+ $ otool -hV libclntsh.dylib.12.1
56
+ Mach header
57
+ magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
58
+ MH_MAGIC_64 X86_64 ALL 0x00 DYLIB 19 2360 DYLDLINK NO_REEXPORTED_DYLIBS MH_HAS_TLV_DESCRIPTORS
59
+
60
+ PostgreSQL client library (`libpq.5.dylib`) installed by [brew][] depends on an OS-supplied LDAP library.
61
+
62
+ $ otool -L libpq.5.dylib
63
+ libpq.5.dylib:
64
+ /usr/local/opt/postgresql/lib/libpq.5.dylib (compatibility version 5.0.0, current version 5.9.0)
65
+ /usr/local/opt/openssl/lib/libssl.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
66
+ /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib (compatibility version 1.0.0, current version 1.0.0)
67
+ /System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)
68
+ /System/Library/Frameworks/LDAP.framework/Versions/A/LDAP (compatibility version 1.0.0, current version 2.4.0)
69
+ /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)
70
+
71
+ The OS-supplied LDAP library is in a two-level namespace.
72
+
73
+ $ otool -hV /System/Library/Frameworks/LDAP.framework/Versions/A/LDAP
74
+ Mach header
75
+ magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
76
+ MH_MAGIC_64 X86_64 ALL 0x00 DYLIB 22 2528 NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS APP_EXTENSION_SAFE
77
+
78
+ As a result, the PostgreSQL client library is free from function interposition.
79
+
80
+ Solution 1
81
+ ----------
82
+
83
+ If you don't connect to PostgreSQL using LDAP, use the following code.
84
+
85
+ require 'oci8' # This must be before "require 'pg'".
86
+ require 'pg'
87
+
88
+ conn = OCI8.new('username/password@dbname.example.com')
89
+ ...
90
+ ... connect to a PostgreSQL server ...
91
+
92
+ Oracle client library uses LDAP functions in `libclntsh.so` because `libclntsh.so`
93
+ is loaded before `libldap_r.so`.
94
+
95
+ Don't connect to PostgreSQL using LDAP because `libpq.so` tries to use
96
+ LDAP functions in `libldap_r.so` but faultily uses functions in `libclntsh.so`.
97
+
98
+ Note for macOS: This fixes all function interposition issues if the LDAP library
99
+ in a two-level namespace.
100
+
101
+ Solution 2
102
+ ----------
103
+
104
+ If LDAP is used to connect to both Oracle and PostgreSQL and the platform
105
+ is Linux or macOS, use ruby-oci8 2.2.4 or later and use the following code.
106
+
107
+ require 'pg'
108
+ require 'oci8' # This must be after "require 'pg'".
109
+
110
+ conn = OCI8.new('username/password@dbname.example.com')
111
+ ...
112
+ ... connect to a PostgreSQL server using LDAP ...
113
+
114
+ PostgreSQL client library uses LDAP functions in `libldap_r.so` because `libldap_r.so`
115
+ is loaded before `libclntsh.so`.
116
+
117
+ Oracle client library uses LDAP functions in `libclntsh.so` because ruby-oci8
118
+ forcedly modifies PLT (Procedure Linkage Table) entries to point to
119
+ functions in `libclntsh.so` if they point to functions in other libraries.
120
+ (PLT is equivalent to IAT (Import Address Table) on Windows.)
121
+
122
+ [mach-o]: https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/MachOTopics/1-Articles/executing_files.html
123
+ [brew]: http://brew.sh/
@@ -0,0 +1,79 @@
1
+ # @title Number Type Mapping between Oracle and Ruby
2
+
3
+ Number Type Mapping between Oracle and Ruby
4
+ ===========================================
5
+
6
+ Default mapping
7
+ ---------------
8
+
9
+ Oracle numbers in select statements are fetched as followings by default:
10
+
11
+ | Oracle Data Type | Ruby Class |
12
+ |---|---|
13
+ | NUMBER(prec) or NUMBER(prec, 0) | Integer |
14
+ | NUMBER(prec, scale) where prec < 15 and scale != 0 | Float |
15
+ | NUMBER(prec, scale) where prec >= 15 and scale != 0 | BigDecimal |
16
+ | FLOAT or FLOAT(prec) | Float |
17
+ | NUMBER without precision and scale | BigDecimal |
18
+ | number type returned by functions or calculated number | BigDecimal |
19
+ | BINARY_FLOAT | Float |
20
+ | BINARY_DOUBLE | Float |
21
+
22
+ When the data type is within Integer or Float class, it is fetched
23
+ as Integer or Float. Otherwise, BigDecimal.
24
+
25
+ Note that the mapping is determined by the column definition in
26
+ select statements, not by the actual value fetched.
27
+ For example the column in `select count(*) from table_name` is
28
+ fetched as BigDecimal because it is returned from `count` function.
29
+
30
+ The mapping is customizable by `OCI8::BindType::Mapping`.
31
+ The default values of Oracle number data type mapping are:
32
+
33
+ # NUMBER or FLOAT data type, used for the first six rows in the above table
34
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::Number
35
+ # BINARY_FLOAT data type, used for the seventh row in the above table
36
+ OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
37
+ # BINARY_DOUBLE data type, used for the eighth row in the above table
38
+ OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::BinaryDouble
39
+
40
+ `OCI8::BindType::Number` checks precision and scale to determine
41
+ ruby class. The first four rows in the above table are hard-coded.
42
+ The fifth and sixth rows are, however, customizable by
43
+ `OCI8::BindType::Mapping[:number_no_prec_setting]` and
44
+ `OCI8::BindType::Mapping[:number_unknown_prec]` respectively.
45
+
46
+ The default values are:
47
+
48
+ OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::BigDecimal
49
+ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::BigDecimal
50
+
51
+ The mapping may be changed as follows in future.
52
+
53
+ | Oracle Data Type | Ruby Class |
54
+ |---|---|
55
+ | NUMBER(prec) or NUMBER(prec, 0) | Integer |
56
+ | other NUMBER | OraNumber |
57
+ | BINARY_FLOAT | Float |
58
+ | BINARY_DOUBLE | Float |
59
+
60
+ Customize mapping
61
+ -----------------
62
+
63
+ Add the following code to fetch all number or float columns as {OraNumber}.
64
+
65
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::OraNumber
66
+
67
+ Otherwise, add the following code to customize the fifth and sixth rows only
68
+ in the above table.
69
+
70
+ OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
71
+ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
72
+
73
+ If you want to fetch numbers as Integer or Float by its actual value, use
74
+ the following code:
75
+
76
+ # Fetch numbers as Integer when their fractional part is zero.
77
+ # Otherwise, Float. For example when a column contains 10 and
78
+ # 10.1, they are fetched as Integer and Float respectively.
79
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::BasicNumberType
@@ -321,13 +321,6 @@ OCILobLocatorIsInit:
321
321
  - CONST OCILobLocator *locp
322
322
  - boolean *is_initialized
323
323
 
324
- # round trip: 1
325
- OCILogoff:
326
- :version: 800
327
- :args:
328
- - OCISvcCtx *svchp
329
- - OCIError *errhp
330
-
331
324
  # round trip: 0
332
325
  OCINumberAbs:
333
326
  :version: 800
@@ -1149,21 +1142,6 @@ OCIIntervalSetYearMonth:
1149
1142
  - sb4 mnth
1150
1143
  - OCIInterval *result
1151
1144
 
1152
- # round trip: 1
1153
- OCILogon2_nb:
1154
- :version: 900
1155
- :args:
1156
- - OCIEnv *envhp
1157
- - OCIError *errhp
1158
- - OCISvcCtx **svchp
1159
- - CONST text *username
1160
- - ub4 uname_len
1161
- - CONST text *password
1162
- - ub4 passwd_len
1163
- - CONST text *dbname
1164
- - ub4 dbname_len
1165
- - ub4 mode
1166
-
1167
1145
  # round trip: 0 (not docmented. I guess.)
1168
1146
  OCIRowidToChar:
1169
1147
  :version: 900
@@ -75,6 +75,21 @@ retry:
75
75
  return rb_external_str_new_with_enc(errbuf, len, oci8_encoding);
76
76
  }
77
77
 
78
+ /*
79
+ * Don't call rb_class_new_instance() with more than one argument in this function.
80
+ * This may be called before OCIError#initialize is defined in lib/oci8/oci8.rb.
81
+ */
82
+ static VALUE oci_exception_new(VALUE klass, VALUE msg, VALUE code, VALUE sql, VALUE parse_error_offset)
83
+ {
84
+ VALUE obj = rb_class_new_instance(NIL_P(msg) ? 0 : 1, &msg, klass);
85
+ if (rb_obj_is_kind_of(obj, eOCIError)) {
86
+ rb_ivar_set(obj, oci8_id_at_code, code);
87
+ rb_ivar_set(obj, oci8_id_at_sql, sql);
88
+ rb_ivar_set(obj, oci8_id_at_parse_error_offset, parse_error_offset);
89
+ }
90
+ return obj;
91
+ }
92
+
78
93
  static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp, const char *file, int line)
79
94
  {
80
95
  VALUE exc;
@@ -84,24 +99,19 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
84
99
  VALUE parse_error_offset = Qnil;
85
100
  VALUE sql = Qnil;
86
101
  int rv;
87
- VALUE args[4];
88
- int numarg = 1;
89
102
 
90
103
  switch (status) {
91
104
  case OCI_ERROR:
92
105
  exc = eOCIError;
93
106
  msg = get_error_msg(errhp, type, "Error", &errcode);
94
- numarg = 4;
95
107
  break;
96
108
  case OCI_SUCCESS_WITH_INFO:
97
109
  exc = eOCISuccessWithInfo;
98
110
  msg = get_error_msg(errhp, type, "Error", &errcode);
99
- numarg = 4;
100
111
  break;
101
112
  case OCI_NO_DATA:
102
113
  exc = eOCINoData;
103
114
  msg = get_error_msg(errhp, type, "No Data", &errcode);
104
- numarg = 4;
105
115
  break;
106
116
  case OCI_INVALID_HANDLE:
107
117
  exc = eOCIInvalidHandle;
@@ -138,11 +148,7 @@ static VALUE oci8_make_exc(dvoid *errhp, sword status, ub4 type, OCIStmt *stmthp
138
148
  sql = rb_external_str_new_with_enc(TO_CHARPTR(text), size, oci8_encoding);
139
149
  }
140
150
  }
141
- args[0] = msg;
142
- args[1] = INT2FIX(errcode);
143
- args[2] = sql;
144
- args[3] = parse_error_offset;
145
- exc = rb_class_new_instance(numarg, args, exc);
151
+ exc = oci_exception_new(exc, msg, INT2FIX(errcode), sql, parse_error_offset);
146
152
  return set_backtrace(exc, file, line);
147
153
  }
148
154
 
@@ -172,22 +178,6 @@ sb4 oci8_get_error_code(OCIError *errhp)
172
178
  return errcode;
173
179
  }
174
180
 
175
- /* This is overwritten by lib/oci8/oci8.rb. */
176
- static VALUE oci8_error_initialize(int argc, VALUE *argv, VALUE self)
177
- {
178
- VALUE msg;
179
- VALUE code;
180
- VALUE sql;
181
- VALUE parse_error_offset;
182
-
183
- rb_scan_args(argc, argv, "04", &msg, &code, &sql, &parse_error_offset);
184
- rb_call_super(argc ? 1 : 0, &msg);
185
- rb_ivar_set(self, oci8_id_at_code, code);
186
- rb_ivar_set(self, oci8_id_at_sql, sql);
187
- rb_ivar_set(self, oci8_id_at_parse_error_offset, parse_error_offset);
188
- return Qnil;
189
- }
190
-
191
181
  void Init_oci8_error(void)
192
182
  {
193
183
  errbufsiz = ERRBUF_EXPAND_LEN;
@@ -217,9 +207,6 @@ void Init_oci8_error(void)
217
207
  rb_define_attr(eOCIError, "sql", 1, 0);
218
208
  rb_define_attr(eOCIError, "parse_error_offset", 1, 0);
219
209
  rb_define_alias(eOCIError, "parseErrorOffset", "parse_error_offset");
220
-
221
- /* This is overwritten by lib/oci8/oci8.rb. */
222
- rb_define_method_nodoc(eOCIError, "initialize", oci8_error_initialize, -1);
223
210
  }
224
211
 
225
212
  void oci8_do_raise(OCIError *errhp, sword status, OCIStmt *stmthp, const char *file, int line)
@@ -278,11 +265,9 @@ VALUE oci8_get_error_message(ub4 msgno, const char *default_msg)
278
265
  void oci8_do_raise_by_msgno(ub4 msgno, const char *default_msg, const char *file, int line)
279
266
  {
280
267
  VALUE msg = oci8_get_error_message(msgno, default_msg);
281
- VALUE args[2];
282
- args[0] = msg;
283
- args[1] = INT2FIX(-1);
268
+ VALUE exc = oci_exception_new(eOCIError, msg, INT2FIX(-1), Qnil, Qnil);
284
269
 
285
- rb_exc_raise(set_backtrace(rb_class_new_instance(2, args, eOCIError), file, line));
270
+ rb_exc_raise(set_backtrace(exc, file, line));
286
271
  }
287
272
 
288
273
  void oci8_check_error_(sword status, oci8_base_t *base, OCIStmt *stmthp, const char *file, int line)