ruby-oci8 2.1.3 → 2.1.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 CHANGED
@@ -1,3 +1,53 @@
1
+ 2013-01-06 KUBO Takehiro <kubo@jiubao.org>
2
+ * NEWS: add changes between 2.1.4 and 2.1.3
3
+ * VERSION: change the version to 2.1.4.
4
+ * docs/platform-specific-issues.md: update solaris-specific document.
5
+ * ext/oci8/connection_pool.c, ext/oci8/encoding.c, ext/oci8/metadata.c,
6
+ ext/oci8/oci8.c,lib/oci8.rb.in, lib/oci8/metadata.rb, lib/oci8/oci8.rb,
7
+ lib/oci8/oracle_version.rb, lib/oci8/properties.rb: update comments for yard.
8
+ * test/test_clob.rb: change a lob size when ORA-24817 is raised to
9
+ pass tests on Windows.
10
+
11
+ 2013-01-03 KUBO Takehiro <kubo@jiubao.org>
12
+ * ext/oci8/oci8.c, lib/oci8/properties.rb: add OCI8.properties[:events_mode]
13
+ to support Fast Application Notification (FAN).
14
+
15
+ 2013-01-03 KUBO Takehiro <kubo@jiubao.org>
16
+ * ext/oci8/extconf.rb, lib/oci8.rb.in: add languange mode to the extension
17
+ library name when ths ruby engine is rubinius and explicitly claim that
18
+ jruby is not supported when it is jruby.
19
+
20
+ 2013-01-03 KUBO Takehiro <kubo@jiubao.org>
21
+ * ext/oci8/encoding.c, lib/oci8/encoding-init.rb: delete an internal method
22
+ OCI8.nls_ratio= when the ruby is 1.9 or greater. nls_ratio is set by
23
+ OCI8.encoding=.
24
+
25
+ 2012-12-23 KUBO Takehiro <kubo@jiubao.org>
26
+ * ext/oci8/lob.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c, test/test_clob.rb:
27
+ fix SEGV when a temporary LOB is freed when OCILobRead returns OCI_NEED_DATA.
28
+ (github issue #20 reported by Edgars Beigarts)
29
+
30
+ 2012-12-18 KUBO Takehiro <kubo@jiubao.org>
31
+ * ext/oci8/error.c, lib/oci8/oci8.rb: change the OCIError constructor to
32
+ accept an Oracle error code as the first parameter and create a message
33
+ which depends on NLS_LANG.
34
+ * lib/oci8/metadata.rb: fix OCI8.describe_table not to follow synonyms
35
+ until stack overflow. Now the recursive level is limited to 20.
36
+ (github issue #26 reported by Brian Henderson)
37
+
38
+ 2012-12-16 KUBO Takehiro <kubo@jiubao.org>
39
+ * ext/oci8/extconf.rb, lib/oci8.rb.in: use RUBY_VERSION instead of
40
+ RbConfig::CONFIG['ruby_version'] to know the ruby ABI version.
41
+ The latter may be changed by the configure option --with-ruby-version.
42
+ (github issue #24 reported by suhrawardi)
43
+
44
+ 2012-12-03 KUBO Takehiro <kubo@jiubao.org>
45
+ * ext/oci8/oraconf.rb: add a script encoding magic comment for ruby 2.0.0 preview2.
46
+ (github issue #25 reported by aboltart)
47
+
48
+ 2012-12-02 KUBO Takehiro <kubo@jiubao.org>
49
+ * test/test_encoding.rb: fix to pass tests with ruby 2.0.0 preview2.
50
+
1
51
  2012-11-11 KUBO Takehiro <kubo@jiubao.org>
2
52
  * ext/oci8/lob.c: use OCILobLocatorAssign_nb (non-blocking version)
3
53
  instead of OCILobLocatorAssign (blocking version).
data/NEWS CHANGED
@@ -1,5 +1,46 @@
1
1
  # @markup markdown
2
2
 
3
+ 2.1.4
4
+ =====
5
+
6
+ New Features
7
+ ------------
8
+
9
+ ### Fast Application Notification (FAN) support
10
+
11
+ Look at {http://php.net/manual/en/oci8.connection.php} to know what is FAN.
12
+ [oci8.events](http://php.net/manual/en/oci8.configuration.php#ini.oci8.events) in PHP
13
+ corresponds to {OCI8.properties OCI8.properties[:events_mode]} in ruby-oci8.
14
+
15
+ Note: You need to set `OCI8.properties[:events_mode]` after `"require 'oci8'"` and before
16
+ any methods which call Oracle OCI functions.
17
+
18
+ Fixed Issues
19
+ ------------
20
+
21
+ - fix SEGV when a temporary LOB is freed when `OCILobRead` returns `OCI_NEED_DATA`.
22
+ See: [github issue #20](https://github.com/kubo/ruby-oci8/issues/20)
23
+
24
+ (reported by Edgars Beigarts)
25
+
26
+ - use `RUBY_VERSION` instead of `RbConfig::CONFIG['ruby_version']` to know the
27
+ ruby ABI version. The latter may be changed by the configure option
28
+ --with-ruby-version.
29
+ See: [github issue #24](https://github.com/kubo/ruby-oci8/issues/24)
30
+
31
+ (reported by suhrawardi)
32
+
33
+ - add a script encoding magic comment for ruby 2.0.0 preview2.
34
+ See: [github issue #25](https://github.com/kubo/ruby-oci8/issues/25)
35
+
36
+ (reported by aboltart)
37
+
38
+ - fix {OCI8#describe_table} not to follow synonyms until stack overflow.
39
+ Now the recursive level is limited to 20.
40
+ See: [github issue #26](https://github.com/kubo/ruby-oci8/issues/26)
41
+
42
+ (reported by Brian Henderson)
43
+
3
44
  2.1.3
4
45
  =====
5
46
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.1.3
1
+ 2.1.4
@@ -71,15 +71,23 @@ Solaris
71
71
  =======
72
72
 
73
73
  You need a same compiler which is used to make ruby itself.
74
-
75
- There are two ruby packages.
76
-
77
- * [Sunfreeware.com](http://www.sunfreeware.com/)
78
- * [Blastwave.org](http://www.blastwave.org/)
79
-
80
- The former is compiled by gcc. The latter is compiled by
81
- [Sun Studio](http://developers.sun.com/sunstudio/).
82
- The both compilers are freely available.
74
+ For example, if the ruby is compiled by gcc, you need gcc. If it is compiled by Oracle Solaris Studio
75
+ (formerly called as Sun Studio), you need Oracle Solaris Studio.
76
+
77
+ If ruby is compiled by gcc and "require 'oci8'" raises "OCI Library Initialization Error",
78
+ you may need to recompile ruby as follows:
79
+
80
+ $ bzip2 -dc ruby-1.9.3-pxxx.tar.bz2 | tar xvf -
81
+ $ cd ruby-1.9.3-pxxx
82
+ $ vi main.c # <- Add RUBY_FUNC_EXPORTED just before "int main(..)" as follows:
83
+ -------------
84
+ RUBY_FUNC_EXPORTED /* Add this line */
85
+ int
86
+ main(int argc, char **argv)
87
+ -------------
88
+ $ ./configure
89
+ $ make
90
+ $ make install
83
91
 
84
92
  If you use Blastwave.org's ruby and want not to install Sun Studio,
85
93
  you can edit rbconfig.rb by your self. [(look at here)](http://forum.textdrive.com/viewtopic.php?id=12630)
@@ -91,8 +99,8 @@ If you use Sunfreeware.com's ruby and
91
99
  prints "yes", you may need to edit rbconfig.rb distributed with the ruby
92
100
  as follows:
93
101
 
94
- from: CONFIG["LDFLAGS"] = "-L. -Wl,-E"
95
- to: CONFIG["LDFLAGS"] = "-L. "
102
+ from: CONFIG["LDFLAGS"] = "-L. -Wl,-E"
103
+ to: CONFIG["LDFLAGS"] = "-L. "
96
104
 
97
105
  FreeBSD
98
106
  =======
@@ -174,9 +174,9 @@ static VALUE oci8_cpool_reinitialize(VALUE self, VALUE conn_min, VALUE conn_max,
174
174
  * call-seq:
175
175
  * pool_name -> string
176
176
  *
177
- * <b>internal use only</b>
178
- *
179
177
  * Retruns the pool name.
178
+ *
179
+ * @private
180
180
  */
181
181
  static VALUE oci8_cpool_pool_name(VALUE self)
182
182
  {
@@ -185,12 +185,14 @@ static VALUE oci8_charset_name2id(VALUE svc, VALUE name)
185
185
  *
186
186
  * @return [Fixnum] NLS ratio
187
187
  * @since 2.1.0
188
+ * @private
188
189
  */
189
190
  static VALUE oci8_get_nls_ratio(VALUE klass)
190
191
  {
191
192
  return INT2NUM(oci8_nls_ratio);
192
193
  }
193
194
 
195
+ #ifndef HAVE_TYPE_RB_ENCODING
194
196
  /*
195
197
  * call-seq:
196
198
  * OCI8.nls_ratio = integer
@@ -201,6 +203,8 @@ static VALUE oci8_get_nls_ratio(VALUE klass)
201
203
  *
202
204
  * @param [Fixnum] integer NLS ratio
203
205
  * @since 2.1.0
206
+ * @private
207
+ * @note ruby 1.8 only
204
208
  */
205
209
  static VALUE oci8_set_nls_ratio(VALUE klass, VALUE val)
206
210
  {
@@ -211,6 +215,7 @@ static VALUE oci8_set_nls_ratio(VALUE klass, VALUE val)
211
215
  oci8_nls_ratio = v;
212
216
  return val;
213
217
  }
218
+ #endif
214
219
 
215
220
  #ifdef HAVE_TYPE_RB_ENCODING
216
221
 
@@ -224,6 +229,7 @@ static VALUE oci8_set_nls_ratio(VALUE klass, VALUE val)
224
229
  * are passed to Oracle, they are converted to +OCI8.encoding+
225
230
  * in advance.
226
231
  *
232
+ * @example
227
233
  * # When OCI8.encoding is ISO-8859-1,
228
234
  * conn.exec('insert into country_code values(:1, :2, :3)',
229
235
  * 'AT', 'Austria', "\u00d6sterreichs")
@@ -243,6 +249,8 @@ static VALUE oci8_set_nls_ratio(VALUE klass, VALUE val)
243
249
  *
244
250
  * @return [Encoding]
245
251
  * @since 2.0.0 and ruby 1.9
252
+ * @private
253
+ * @see OCI8.client_charset_name
246
254
  */
247
255
  static VALUE oci8_get_encoding(VALUE klass)
248
256
  {
@@ -259,13 +267,16 @@ static VALUE oci8_get_encoding(VALUE klass)
259
267
  *
260
268
  * @param [Encoding] enc
261
269
  * @since 2.0.0 and ruby 1.9
270
+ * @private
262
271
  */
263
272
  static VALUE oci8_set_encoding(VALUE klass, VALUE encoding)
264
273
  {
265
274
  if (NIL_P(encoding)) {
266
275
  oci8_encoding = NULL;
276
+ oci8_nls_ratio = 1;
267
277
  } else {
268
278
  oci8_encoding = rb_to_encoding(encoding);
279
+ oci8_nls_ratio = rb_enc_mbmaxlen(oci8_encoding);
269
280
  }
270
281
  return encoding;
271
282
  }
@@ -287,7 +298,9 @@ void Init_oci8_encoding(VALUE cOCI8)
287
298
  rb_define_method(cOCI8, "charset_name2id", oci8_charset_name2id, 1);
288
299
  rb_define_method(cOCI8, "charset_id2name", oci8_charset_id2name, 1);
289
300
  rb_define_singleton_method(cOCI8, "nls_ratio", oci8_get_nls_ratio, 0);
301
+ #ifndef HAVE_TYPE_RB_ENCODING
290
302
  rb_define_singleton_method(cOCI8, "nls_ratio=", oci8_set_nls_ratio, 1);
303
+ #endif
291
304
  #ifdef HAVE_TYPE_RB_ENCODING
292
305
  rb_define_singleton_method(cOCI8, "encoding", oci8_get_encoding, 0);
293
306
  rb_define_singleton_method(cOCI8, "encoding=", oci8_set_encoding, 1);
@@ -160,31 +160,6 @@ static VALUE set_backtrace(VALUE exc, const char *file, int line)
160
160
  return exc;
161
161
  }
162
162
 
163
- /*
164
- * call-seq:
165
- * initialize(message, code = nil, sql = nil, parse_error_offset = nil)
166
- *
167
- * Creates a new OCIError object.
168
- *
169
- * @example
170
- * OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1)
171
- * # => #<OCIError: ORA-00001: unique constraint (%s.%s) violated>
172
- */
173
- static VALUE oci8_error_initialize(int argc, VALUE *argv, VALUE self)
174
- {
175
- VALUE msg;
176
- VALUE code;
177
- VALUE sql;
178
- VALUE parse_error_offset;
179
-
180
- rb_scan_args(argc, argv, "04", &msg, &code, &sql, &parse_error_offset);
181
- rb_call_super(argc > 1 ? 1 : argc, argv);
182
- rb_ivar_set(self, oci8_id_at_code, code);
183
- rb_ivar_set(self, oci8_id_at_sql, sql);
184
- rb_ivar_set(self, oci8_id_at_parse_error_offset, parse_error_offset);
185
- return Qnil;
186
- }
187
-
188
163
  sb4 oci8_get_error_code(OCIError *errhp)
189
164
  {
190
165
  sb4 errcode = -1;
@@ -214,8 +189,6 @@ void Init_oci8_error(void)
214
189
  eOCIContinue = rb_define_class("OCIContinue", eOCIException);
215
190
  eOCISuccessWithInfo = rb_define_class("OCISuccessWithInfo", eOCIError);
216
191
 
217
- rb_define_method(eOCIError, "initialize", oci8_error_initialize, -1);
218
-
219
192
  /*
220
193
  * @attr_reader [Integer] code error code
221
194
  */
@@ -134,14 +134,57 @@ replace_keyword(File.dirname(__FILE__) + '/../../lib/oci8.rb.in', '../../lib/oci
134
134
  ruby_engine = (defined? RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
135
135
 
136
136
  so_basename = 'oci8lib_'
137
- if ruby_engine == 'ruby'
138
- # Config::CONFIG["ruby_version"] indicates the ruby API version.
139
- # 1.8 - ruby 1.8.x
140
- # 1.9.1 - ruby 1.9.1, 1.9.2
141
- # 2.0.0 - ruby 2.0.0
142
- so_basename += RbConfig::CONFIG["ruby_version"].gsub(/\W/, '')
137
+ case ruby_engine
138
+ when 'ruby'
139
+ # The extension library name includes the ruby ABI (application binary interface)
140
+ # version. It is for binary gems which contain more than one extension library
141
+ # and use correct one depending on the ABI version.
142
+ #
143
+ # ruby version | ABI version
144
+ # --------------+--------------
145
+ # 1.8.6 | 1.8
146
+ # 1.8.7 | 1.8
147
+ # --------------+--------------
148
+ # 1.9.0 | 1.9.0
149
+ # 1.9.1 | 1.9.1
150
+ # 1.9.2 | 1.9.1
151
+ # 1.9.3 | 1.9.1
152
+ # --------------+--------------
153
+ # 2.0.0 | 2.0.0
154
+ # 2.0.1 | 2.0.1 (See: [ruby-core:49578])
155
+ # ... | ...
156
+ #
157
+ # Note: The ruby ABI version is same with RbConfig::CONFIG['ruby_version']
158
+ # if it wasn't explicitly changed by the configure option --with-ruby-version.
159
+ #
160
+ case RUBY_VERSION
161
+ when /^2\.0/
162
+ so_basename += RUBY_VERSION.gsub(/\W/, '')
163
+ when /^1\.9\.0/
164
+ raise 'unsupported ruby version: 1.9.0'
165
+ when /^1\.9/
166
+ so_basename += '191'
167
+ when /^1\.8/
168
+ so_basename += '18'
169
+ else
170
+ raise 'unsupported ruby version: ' + RUBY_VERSION
171
+ end
172
+ when 'rbx'
173
+ # "rbx -X18" and "rbx -X19" use different C header files.
174
+ case RUBY_VERSION
175
+ when /^2\.0/
176
+ so_basename += 'rbx20'
177
+ when /^1\.9/
178
+ so_basename += 'rbx19'
179
+ when /^1\.8/
180
+ so_basename += 'rbx18'
181
+ else
182
+ raise 'unsupported language mode: ' + RUBY_VERSION
183
+ end
184
+ when 'jruby'
185
+ raise "Ruby-oci8 doesn't support jruby because its C extension support is in development in jruby 1.6 and deprecated in jruby 1.7."
143
186
  else
144
- so_basename += ruby_engine
187
+ raise 'unsupported ruby engine: ' + RUBY_ENGINE
145
188
  end
146
189
 
147
190
  $defs << "-DInit_oci8lib=Init_#{so_basename}"
@@ -554,12 +554,24 @@ static VALUE oci8_lob_read(int argc, VALUE *argv, VALUE self)
554
554
  /* initialize buf in zeros everytime to check a nul characters. */
555
555
  memset(buf, 0, sizeof(buf));
556
556
  rv = OCILobRead_nb(svcctx, svcctx->base.hp.svc, oci8_errhp, lob->base.hp.lob, &amt, lob->pos + 1, buf, sizeof(buf), NULL, NULL, 0, lob->csfrm);
557
- if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22289) {
558
- /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */
559
- if (lob->state == S_BFILE_CLOSE)
560
- continue;
561
- }
562
- if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA) {
557
+ svcctx->suppress_free_temp_lobs = 0;
558
+ switch (rv) {
559
+ case OCI_SUCCESS:
560
+ break;
561
+ case OCI_NEED_DATA:
562
+ /* prevent OCILobFreeTemporary() from being called.
563
+ * See: https://github.com/kubo/ruby-oci8/issues/20
564
+ */
565
+ svcctx->suppress_free_temp_lobs = 1;
566
+ break;
567
+ case OCI_ERROR:
568
+ if (oci8_get_error_code(oci8_errhp) == 22289) {
569
+ /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */
570
+ if (lob->state == S_BFILE_CLOSE)
571
+ continue;
572
+ }
573
+ /* FALLTHROUGH */
574
+ default:
563
575
  chker2(rv, &svcctx->base);
564
576
  }
565
577
 
@@ -159,6 +159,19 @@ static VALUE oci8_do_describe(VALUE self, void *objptr, ub4 objlen, ub1 objtype,
159
159
  return oci8_metadata_create(parmhp, self, obj);
160
160
  }
161
161
 
162
+ /*
163
+ * call-seq:
164
+ * __describe(name, klass, check_public)
165
+ *
166
+ * @param [String] name object name
167
+ * @param [subclass of OCI8::Metadata::Base] klass
168
+ * @param [Boolean] check_public +true+ to look up the object as a public synonym when
169
+ * the object does not exist in the current schema and
170
+ * the name includes no dots.
171
+ * @return [subclass of OCI8::Metadata::Base]
172
+ *
173
+ * @private
174
+ */
162
175
  static VALUE oci8_describe(VALUE self, VALUE name, VALUE klass, VALUE check_public)
163
176
  {
164
177
  OCI8SafeStringValue(name);
@@ -2,7 +2,7 @@
2
2
  /*
3
3
  * oci8.c - part of ruby-oci8
4
4
  *
5
- * Copyright (C) 2002-2011 KUBO Takehiro <kubo@jiubao.org>
5
+ * Copyright (C) 2002-2013 KUBO Takehiro <kubo@jiubao.org>
6
6
  *
7
7
  */
8
8
  #include "oci8.h"
@@ -171,25 +171,56 @@ static VALUE oci8_s_oracle_client_vernum(VALUE klass)
171
171
  return oracle_client_vernum;
172
172
  }
173
173
 
174
- static VALUE oci8_s_set_property(VALUE klass, VALUE name, VALUE val)
174
+ /*
175
+ * call-seq:
176
+ * OCI8.__get_prop(key)
177
+ *
178
+ * @param [Fixnum] key 1 or 2
179
+ *
180
+ * @private
181
+ */
182
+ static VALUE oci8_s_get_prop(VALUE klass, VALUE key)
175
183
  {
176
- const char *name_str;
177
-
178
- Check_Type(name, T_SYMBOL);
179
- name_str = rb_id2name(SYM2ID(name));
180
- if (strcmp(name_str, "float_conversion_type") == 0) {
181
- const char *val_str;
182
- Check_Type(val, T_SYMBOL);
183
- val_str = rb_id2name(SYM2ID(val));
184
- if (strcmp(val_str, "ruby") == 0) {
185
- oci8_float_conversion_type_is_ruby = 1;
186
- } else if (strcmp(val_str, "oracle") == 0) {
187
- oci8_float_conversion_type_is_ruby = 0;
188
- } else {
189
- rb_raise(rb_eArgError, "float_conversion_type's value should be either :ruby or :oracle.");
184
+ switch (NUM2INT(key)) {
185
+ case 1:
186
+ return oci8_float_conversion_type_is_ruby ? Qtrue : Qfalse;
187
+ case 2:
188
+ return UINT2NUM(oci8_env_mode);
189
+ default:
190
+ rb_raise(rb_eArgError, "Unknown prop %d", NUM2INT(key));
191
+ }
192
+ }
193
+
194
+
195
+ /*
196
+ * call-seq:
197
+ * OCI8.__set_prop(key, value)
198
+ *
199
+ * @param [Fixnum] key 1 or 2
200
+ * @param [Object] value depends on +key+.
201
+ *
202
+ * @private
203
+ */
204
+ static VALUE oci8_s_set_prop(VALUE klass, VALUE key, VALUE val)
205
+ {
206
+ switch (NUM2INT(key)) {
207
+ case 1:
208
+ oci8_float_conversion_type_is_ruby = RTEST(val) ? 1 : 0;
209
+ break;
210
+ case 2:
211
+ /*
212
+ * Changes the OCI environment mode which will be passed to the second
213
+ * argument of the OCI function OCIEnvCreate.
214
+ */
215
+ if (oci8_global_envhp != NULL) {
216
+ rb_raise(rb_eRuntimeError, "The OCI Environment has been alreadly initialized. It cannot be changed after even one OCI function is called.");
190
217
  }
218
+ oci8_env_mode = NUM2UINT(val);
219
+ break;
220
+ default:
221
+ rb_raise(rb_eArgError, "Unknown prop %d", NUM2INT(key));
191
222
  }
192
- return Qnil;
223
+ return klass;
193
224
  }
194
225
 
195
226
  /*
@@ -254,6 +285,7 @@ void oci8_do_parse_connect_string(VALUE conn_str, VALUE *user, VALUE *pass, VALU
254
285
  * "scott/tiger@oradb.example.com" -> ["scott", "tiger", "oradb.example.com", nil]
255
286
  * "sys/change_on_install as sysdba" -> ["sys", "change_on_install", nil, :SYSDBA]
256
287
  *
288
+ * @private
257
289
  */
258
290
  static VALUE oci8_parse_connect_string(VALUE self, VALUE conn_str)
259
291
  {
@@ -365,9 +397,9 @@ static const oci8_logoff_strategy_t complex_logoff = {
365
397
  * call-seq:
366
398
  * logon2(username, password, dbname, mode) -> connection
367
399
  *
368
- * <b>internal use only</b>
369
- *
370
400
  * Creates a simple logon session by the OCI function OCILogon2().
401
+ *
402
+ * @private
371
403
  */
372
404
  static VALUE oci8_logon2(VALUE self, VALUE username, VALUE password, VALUE dbname, VALUE mode)
373
405
  {
@@ -417,10 +449,10 @@ static VALUE oci8_logon2(VALUE self, VALUE username, VALUE password, VALUE dbnam
417
449
  * call-seq:
418
450
  * allocate_handles()
419
451
  *
420
- * <b>internal use only</b>
421
- *
422
452
  * Allocates a service context handle, a session handle and a
423
453
  * server handle to use explicit attach and begin-session calls.
454
+ *
455
+ * @private
424
456
  */
425
457
  static VALUE oci8_allocate_handles(VALUE self)
426
458
  {
@@ -457,9 +489,9 @@ static VALUE oci8_allocate_handles(VALUE self)
457
489
  * call-seq:
458
490
  * server_attach(dbname, mode)
459
491
  *
460
- * <b>internal use only</b>
461
- *
462
492
  * Attachs to the server by the OCI function OCIServerAttach().
493
+ *
494
+ * @private
463
495
  */
464
496
  static VALUE oci8_server_attach(VALUE self, VALUE dbname, VALUE attach_mode)
465
497
  {
@@ -499,9 +531,9 @@ static VALUE oci8_server_attach(VALUE self, VALUE dbname, VALUE attach_mode)
499
531
  * call-seq:
500
532
  * session_begin(cred, mode)
501
533
  *
502
- * <b>internal use only</b>
503
- *
504
534
  * Begins the session by the OCI function OCISessionBegin().
535
+ *
536
+ * @private
505
537
  */
506
538
  static VALUE oci8_session_begin(VALUE self, VALUE cred, VALUE mode)
507
539
  {
@@ -767,9 +799,9 @@ static VALUE oci8_set_prefetch_rows(VALUE self, VALUE val)
767
799
  *
768
800
  * Returns a numerical format of the Oracle server version.
769
801
  *
770
- * See also: #oracle_server_version
771
- *
802
+ * @see OCI8#oracle_server_version
772
803
  * @since 2.0.1
804
+ * @private
773
805
  */
774
806
  static VALUE oci8_oracle_server_vernum(VALUE self)
775
807
  {
@@ -1121,7 +1153,8 @@ void Init_oci8(VALUE *out)
1121
1153
 
1122
1154
  rb_define_const(cOCI8, "VERSION", rb_obj_freeze(rb_usascii_str_new_cstr(OCI8LIB_VERSION)));
1123
1155
  rb_define_singleton_method_nodoc(cOCI8, "oracle_client_vernum", oci8_s_oracle_client_vernum, 0);
1124
- rb_define_singleton_method_nodoc(cOCI8, "__set_property", oci8_s_set_property, 2);
1156
+ rb_define_singleton_method(cOCI8, "__get_prop", oci8_s_get_prop, 1);
1157
+ rb_define_singleton_method(cOCI8, "__set_prop", oci8_s_set_prop, 2);
1125
1158
  rb_define_singleton_method(cOCI8, "error_message", oci8_s_error_message, 1);
1126
1159
  rb_define_private_method(cOCI8, "parse_connect_string", oci8_parse_connect_string, 1);
1127
1160
  rb_define_private_method(cOCI8, "logon2", oci8_logon2, 4);
@@ -1145,7 +1178,6 @@ void Init_oci8(VALUE *out)
1145
1178
  rb_define_method(cOCI8, "module=", oci8_set_module, 1);
1146
1179
  rb_define_method(cOCI8, "action=", oci8_set_action, 1);
1147
1180
  rb_define_method(cOCI8, "client_info=", oci8_set_client_info, 1);
1148
- rb_define_attr(cOCI8, "last_error", 1, 1);
1149
1181
  *out = cOCI8;
1150
1182
  }
1151
1183
 
@@ -361,6 +361,7 @@ typedef struct oci8_svcctx {
361
361
  rb_pid_t pid;
362
362
  unsigned char state;
363
363
  char is_autocommit;
364
+ char suppress_free_temp_lobs;
364
365
  #ifdef NATIVE_THREAD_WITH_GVL
365
366
  char non_blocking;
366
367
  #endif
@@ -229,44 +229,45 @@ static void *free_temp_lob(void *user_data)
229
229
  /* ruby 1.9 */
230
230
  sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data)
231
231
  {
232
- oci8_temp_lob_t *lob;
233
232
  OCIError *errhp = oci8_errhp;
234
233
 
235
234
  if (!NIL_P(svcctx->executing_thread)) {
236
235
  rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread");
237
236
  }
238
237
 
239
- lob = svcctx->temp_lobs;
240
- while (lob != NULL) {
241
- oci8_temp_lob_t *lob_next = lob->next;
238
+ if (!svcctx->suppress_free_temp_lobs) {
239
+ oci8_temp_lob_t *lob = svcctx->temp_lobs;
240
+ while (lob != NULL) {
241
+ oci8_temp_lob_t *lob_next = lob->next;
242
242
 
243
- if (svcctx->non_blocking) {
244
- free_temp_lob_arg_t arg;
245
- sword rv;
243
+ if (svcctx->non_blocking) {
244
+ free_temp_lob_arg_t arg;
245
+ sword rv;
246
246
 
247
- arg.svcctx = svcctx;
248
- arg.svchp = svcctx->base.hp.svc;
249
- arg.errhp = errhp;
250
- arg.lob = lob->lob;
247
+ arg.svcctx = svcctx;
248
+ arg.svchp = svcctx->base.hp.svc;
249
+ arg.errhp = errhp;
250
+ arg.lob = lob->lob;
251
251
 
252
- svcctx->executing_thread = rb_thread_current();
252
+ svcctx->executing_thread = rb_thread_current();
253
253
  #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL
254
- rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx);
254
+ rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx);
255
255
  #else
256
- rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx);
256
+ rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx);
257
257
  #endif
258
- if (rv == OCI_ERROR) {
259
- if (oci8_get_error_code(errhp) == 1013) {
260
- rb_raise(eOCIBreak, "Canceled by user request.");
258
+ if (rv == OCI_ERROR) {
259
+ if (oci8_get_error_code(errhp) == 1013) {
260
+ rb_raise(eOCIBreak, "Canceled by user request.");
261
+ }
261
262
  }
263
+ } else {
264
+ OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob);
262
265
  }
263
- } else {
264
- OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob);
265
- }
266
- OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB);
266
+ OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB);
267
267
 
268
- xfree(lob);
269
- svcctx->temp_lobs = lob = lob_next;
268
+ xfree(lob);
269
+ svcctx->temp_lobs = lob = lob_next;
270
+ }
270
271
  }
271
272
 
272
273
  if (svcctx->non_blocking) {
@@ -1,3 +1,4 @@
1
+ # coding: ascii
1
2
  require 'mkmf'
2
3
 
3
4
  # compatibility for ruby-1.9
@@ -26,14 +26,34 @@ end
26
26
  ruby_engine = (defined? RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
27
27
 
28
28
  so_basename = 'oci8lib_'
29
- if ruby_engine == 'ruby'
30
- # The suffix number indicates the ruby API version.
31
- # 1.8 - ruby 1.8.x
32
- # 1.9.1 - ruby 1.9.1, 1.9.2
33
- # 2.0.0 - ruby 2.0.0-dev at the present time.
29
+ case ruby_engine
30
+ when 'ruby'
31
+ # The extension library name includes the ruby ABI (application binary interface)
32
+ # version. It is for binary gems which contain more than one extension library
33
+ # and use correct one depending on the ABI version.
34
+ #
35
+ # ruby version | ABI version
36
+ # --------------+--------------
37
+ # 1.8.6 | 1.8
38
+ # 1.8.7 | 1.8
39
+ # --------------+--------------
40
+ # 1.9.0 | 1.9.0
41
+ # 1.9.1 | 1.9.1
42
+ # 1.9.2 | 1.9.1
43
+ # 1.9.3 | 1.9.1
44
+ # --------------+--------------
45
+ # 2.0.0 | 2.0.0
46
+ # 2.0.1 | 2.0.1 (See: [ruby-core:49578])
47
+ # ... | ...
48
+ #
49
+ # Note: The ruby ABI version is same with RbConfig::CONFIG['ruby_version']
50
+ # if it wasn't explicitly changed by the configure option --with-ruby-version.
51
+ #
34
52
  case RUBY_VERSION
35
53
  when /^2\.0/
36
- so_basename += '200'
54
+ so_basename += RUBY_VERSION.gsub(/\W/, '')
55
+ when /^1\.9\.0/
56
+ raise 'unsupported ruby version: 1.9.0'
37
57
  when /^1\.9/
38
58
  so_basename += '191'
39
59
  when /^1\.8/
@@ -41,8 +61,22 @@ if ruby_engine == 'ruby'
41
61
  else
42
62
  raise 'unsupported ruby version: ' + RUBY_VERSION
43
63
  end
64
+ when 'rbx'
65
+ # "rbx -X18" and "rbx -X19" use different C header files.
66
+ case RUBY_VERSION
67
+ when /^2\.0/
68
+ so_basename += 'rbx20'
69
+ when /^1\.9/
70
+ so_basename += 'rbx19'
71
+ when /^1\.8/
72
+ so_basename += 'rbx18'
73
+ else
74
+ raise 'unsupported language mode: ' + RUBY_VERSION
75
+ end
76
+ when 'jruby'
77
+ raise "Ruby-oci8 doesn't support jruby because its C extension support is in development in jruby 1.6 and deprecated in jruby 1.7."
44
78
  else
45
- so_basename += ruby_engine
79
+ raise 'unsupported ruby engine: ' + RUBY_ENGINE
46
80
  end
47
81
  require so_basename
48
82
 
@@ -89,6 +123,7 @@ class OCI8
89
123
  # OCIClientVersion().
90
124
  #
91
125
  # @return [OCI8::OracleVersion] Oracle client version
126
+ # @see OCI8#oracle_server_version
92
127
  def self.oracle_client_version
93
128
  @@oracle_client_version
94
129
  end
@@ -39,26 +39,6 @@ class OCI8
39
39
  @@client_charset_name = 'US7ASCII'
40
40
  end
41
41
 
42
- # NLS ratio, maximum number of bytes per one chracter
43
- case @@client_charset_name
44
- when 'UTF8'
45
- OCI8.nls_ratio = 3
46
- when 'AL16UTF16'
47
- OCI8.nls_ratio = 4
48
- when /^[[:alpha:]]+(\d+)/
49
- # convert maximum number of bits per one chracter to NLS ratio.
50
- # charset name max bits max bytes
51
- # ------------ -------- ---------
52
- # US7ASCII 7 1
53
- # WE8ISO8859P1 8 1
54
- # JA16SJIS 16 2
55
- # AL32UTF8 32 4
56
- # ...
57
- OCI8.nls_ratio = (($1.to_i + 7) >> 3)
58
- else
59
- raise "Unknown NLS character set name format: #{@@client_charset_name}"
60
- end
61
-
62
42
  # Ruby encoding name for ruby 1.9.
63
43
  if OCI8.respond_to? :encoding
64
44
  if defined? DEFAULT_OCI8_ENCODING
@@ -75,5 +55,25 @@ class OCI8
75
55
  end
76
56
  end
77
57
  OCI8.encoding = enc
58
+ else
59
+ # NLS ratio, maximum number of bytes per one chracter
60
+ case @@client_charset_name
61
+ when 'UTF8'
62
+ OCI8.nls_ratio = 3
63
+ when 'AL16UTF16'
64
+ OCI8.nls_ratio = 4
65
+ when /^[[:alpha:]]+(\d+)/
66
+ # convert maximum number of bits per one chracter to NLS ratio.
67
+ # charset name max bits max bytes
68
+ # ------------ -------- ---------
69
+ # US7ASCII 7 1
70
+ # WE8ISO8859P1 8 1
71
+ # JA16SJIS 16 2
72
+ # AL32UTF8 32 4
73
+ # ...
74
+ OCI8.nls_ratio = (($1.to_i + 7) >> 3)
75
+ else
76
+ raise "Unknown NLS character set name format: #{@@client_charset_name}"
77
+ end
78
78
  end
79
79
  end
@@ -1985,72 +1985,115 @@ class OCI8
1985
1985
  =end
1986
1986
  end # OCI8::Metadata
1987
1987
 
1988
- # return a subclass of OCI8::Metadata::Base
1989
- # which has information about _object_name_.
1990
- # OCI8::Metadata::Table, OCI8::Metadata::View,
1991
- # OCI8::Metadata::Procedure, OCI8::Metadata::Function,
1992
- # OCI8::Metadata::Package, OCI8::Metadata::Type,
1993
- # OCI8::Metadata::Synonym or OCI8::Metadata::Sequence
1988
+ # Returns object information.
1989
+ #
1990
+ # The return type is depends on the object type.
1991
+ #
1992
+ # Oracle type:: Ruby type
1993
+ # Table:: {OCI8::Metadata::Table}
1994
+ # View:: {OCI8::Metadata::View}
1995
+ # Procedure:: {OCI8::Metadata::Procedure}
1996
+ # Function:: {OCI8::Metadata::Function}
1997
+ # Package:: {OCI8::Metadata::Package}
1998
+ # Type:: {OCI8::Metadata::Type}
1999
+ # Synonym:: {OCI8::Metadata::Synonym}
2000
+ # Sequence:: {OCI8::Metadata::Sequence}
2001
+ #
2002
+ # @param [String] object_name
2003
+ # @return [a subclass of OCI8::Metadata::Base]
1994
2004
  def describe_any(object_name)
1995
2005
  __describe(object_name, OCI8::Metadata::Unknown, true)
1996
2006
  end
1997
- # returns a OCI8::Metadata::Table or a OCI8::Metadata::View. If the
1998
- # name is a current schema's synonym name or a public synonym name,
1999
- # it returns a OCI8::Metadata::Table or a OCI8::Metadata::View which
2007
+ # Returns table or view information. If the name is a current schema's synonym
2008
+ # name or a public synonym name, it returns table or view information which
2000
2009
  # the synonym refers.
2001
2010
  #
2002
- # If the second argument is true, this returns a
2003
- # OCI8::Metadata::Table in the current schema.
2011
+ # If +table_only+ is true, it checks tables in the current schema.
2012
+ #
2013
+ # @param [String] table_name
2014
+ # @param [Boolean] table_only (default: false)
2015
+ # @return [OCI8::Metadata::Table or OCI8::Metadata::View]
2004
2016
  def describe_table(table_name, table_only = false)
2005
2017
  if table_only
2006
2018
  # check my own tables only.
2007
2019
  __describe(table_name, OCI8::Metadata::Table, false)
2008
2020
  else
2009
2021
  # check tables, views, synonyms and public synonyms.
2010
- metadata = __describe(table_name, OCI8::Metadata::Unknown, true)
2011
- case metadata
2012
- when OCI8::Metadata::Table, OCI8::Metadata::View
2013
- metadata
2014
- when OCI8::Metadata::Synonym
2015
- describe_table(metadata.translated_name)
2016
- else
2017
- raise OCIError.new("ORA-04043: object #{table_name} does not exist", 4043)
2022
+ recursive_level = 20
2023
+ recursive_level.times do
2024
+ metadata = __describe(table_name, OCI8::Metadata::Unknown, true)
2025
+ case metadata
2026
+ when OCI8::Metadata::Table, OCI8::Metadata::View
2027
+ return metadata
2028
+ when OCI8::Metadata::Synonym
2029
+ table_name = metadata.translated_name
2030
+ else
2031
+ raise OCIError.new(4043, table_name) # ORA-04043: object %s does not exist
2032
+ end
2018
2033
  end
2034
+ raise OCIError.new(36, recursive_level) # ORA-00036: maximum number of recursive SQL levels (%s) exceeded
2019
2035
  end
2020
2036
  end
2021
- # returns a OCI8::Metadata::View in the current schema.
2037
+ # Returns view information
2038
+ #
2039
+ # @param [String] view_name
2040
+ # @return [OCI8::Metadata::View]
2022
2041
  def describe_view(view_name)
2023
2042
  __describe(view_name, OCI8::Metadata::View, false)
2024
2043
  end
2025
- # returns a OCI8::Metadata::Procedure in the current schema.
2044
+ # Returns procedure information
2045
+ #
2046
+ # @param [String] procedure_name
2047
+ # @return [OCI8::Metadata::Procedure]
2026
2048
  def describe_procedure(procedure_name)
2027
2049
  __describe(procedure_name, OCI8::Metadata::Procedure, false)
2028
2050
  end
2029
- # returns a OCI8::Metadata::Function in the current schema.
2051
+ # Returns function information
2052
+ #
2053
+ # @param [String] function_name
2054
+ # @return [OCI8::Metadata::Function]
2030
2055
  def describe_function(function_name)
2031
2056
  __describe(function_name, OCI8::Metadata::Function, false)
2032
2057
  end
2033
- # returns a OCI8::Metadata::Package in the current schema.
2058
+ # Returns package information
2059
+ #
2060
+ # @param [String] package_name
2061
+ # @return [OCI8::Metadata::Package]
2034
2062
  def describe_package(package_name)
2035
2063
  __describe(package_name, OCI8::Metadata::Package, false)
2036
2064
  end
2037
- # returns a OCI8::Metadata::Type in the current schema.
2065
+ # Returns type information
2066
+ #
2067
+ # @param [String] type_name
2068
+ # @return [OCI8::Metadata::Type]
2038
2069
  def describe_type(type_name)
2039
2070
  __describe(type_name, OCI8::Metadata::Type, false)
2040
2071
  end
2041
- # returns a OCI8::Metadata::Synonym in the current schema.
2072
+ # Returns synonym information
2073
+ #
2074
+ # @param [String] synonym_name
2075
+ # @return [OCI8::Metadata::Synonym]
2042
2076
  def describe_synonym(synonym_name, check_public_also = true)
2043
2077
  __describe(synonym_name, OCI8::Metadata::Synonym, check_public_also)
2044
2078
  end
2045
- # returns a OCI8::Metadata::Sequence in the current schema.
2079
+ # Returns sequence information
2080
+ #
2081
+ # @param [String] sequence_name
2082
+ # @return [OCI8::Metadata::Sequence]
2046
2083
  def describe_sequence(sequence_name)
2047
2084
  __describe(sequence_name, OCI8::Metadata::Sequence, false)
2048
2085
  end
2049
- # returns a OCI8::Metadata::Schema in the database.
2086
+ # Returns schema information
2087
+ #
2088
+ # @param [String] schema_name
2089
+ # @return [OCI8::Metadata::Schema]
2050
2090
  def describe_schema(schema_name)
2051
2091
  __describe(schema_name, OCI8::Metadata::Schema, false)
2052
2092
  end
2053
- # returns a OCI8::Metadata::Database.
2093
+ # Returns database information
2094
+ #
2095
+ # @param [String] database_name
2096
+ # @return [OCI8::Metadata::Database]
2054
2097
  def describe_database(database_name)
2055
2098
  __describe(database_name, OCI8::Metadata::Database, false)
2056
2099
  end
@@ -26,8 +26,10 @@ require 'yaml'
26
26
  # value_for_the_second_parameter)
27
27
  class OCI8
28
28
 
29
- # call-seq:
30
- # new(username, password, dbname = nil, privilege = nil)
29
+ # @return [OCIError]
30
+ attr_accessor :last_error
31
+
32
+ # @overload initialize(username, password, dbname = nil, privilege = nil)
31
33
  #
32
34
  # Connects to an Oracle database server by +username+ and +password+
33
35
  # at +dbname+ as +privilege+.
@@ -337,14 +339,14 @@ class OCI8
337
339
  end
338
340
  end
339
341
 
342
+ # @private
340
343
  def inspect
341
344
  "#<OCI8:#{username}>"
342
345
  end
343
346
 
344
- # Returns an OCI8::OracleVersion of the Oracle server version.
345
- #
346
- # See also: OCI8.oracle_client_version
347
+ # Returns the Oracle server version.
347
348
  #
349
+ # @see OCI8.oracle_client_version
348
350
  # @return [OCI8::OracleVersion]
349
351
  def oracle_server_version
350
352
  unless defined? @oracle_server_version
@@ -365,7 +367,7 @@ class OCI8
365
367
  @oracle_server_version
366
368
  end
367
369
 
368
- # Returns the Oracle database character set name.
370
+ # Returns the Oracle database character set name such as AL32UTF8.
369
371
  #
370
372
  # @since 2.1.0
371
373
  # @return [String] Oracle database character set name
@@ -373,15 +375,74 @@ class OCI8
373
375
  charset_id2name(@server_handle.send(:attr_get_ub2, OCI_ATTR_CHARSET_ID))
374
376
  end
375
377
 
376
- # Returns the client-side Oracle character set name.
378
+ # Returns the client-side Oracle character set name such as AL32UTF8.
377
379
  #
378
380
  # @since 2.1.0
379
381
  # @return [String] client-side character set name
382
+ # @private
383
+ # @see OCI8.encoding
380
384
  def self.client_charset_name
381
385
  @@client_charset_name
382
386
  end
383
387
  end
384
388
 
389
+ class OCIError
390
+
391
+ # @overload initialize(message, error_code = nil, sql_stmt = nil, parse_error_offset = nil)
392
+ # Creates a new OCIError object with specified parameters.
393
+ #
394
+ # @param [String] message error message
395
+ # @param [Integer] error_code Oracle error code
396
+ # @param [String] sql_stmt SQL statement
397
+ # @param [Integer] parse_error_offset
398
+ #
399
+ # @example
400
+ # OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1, 'insert into table_name values (1)', )
401
+ # # => #<OCIError: ORA-00001: unique constraint (%s.%s) violated>
402
+ # #<OCIError: ORA-00923: FROM keyword not found where expected>
403
+ # "select sysdate"
404
+ # 923
405
+ # 14
406
+ #
407
+ # @overload initialize(error_code, *params)
408
+ # Creates a new OCIError object with the error message which corresponds to the specified
409
+ # Oracle error code.
410
+ #
411
+ # @param [Integer] error_code Oracle error code
412
+ # @param [String, ...] params parameters which replace '%s'
413
+ #
414
+ # @example
415
+ # # without parameters
416
+ # OCIError.new(4043)
417
+ # # When NLS_LANG=american_america.AL32UTF8
418
+ # # => #<OCIError: ORA-04043: object %s does not exist>
419
+ # # When NLS_LANG=german_germany.AL32UTF8
420
+ # # => #<OCIError: ORA-04043: Objekt %s ist nicht vorhanden>
421
+ #
422
+ # # with one parameter
423
+ # OCIError.new(4043, 'table_name')
424
+ # # When NLS_LANG=american_america.AL32UTF8
425
+ # # => #<OCIError: ORA-04043: object table_name does not exist>
426
+ # # When NLS_LANG=german_germany.AL32UTF8
427
+ # # => #<OCIError: ORA-04043: Objekt table_name ist nicht vorhanden>
428
+ #
429
+ def initialize(*args)
430
+ if args.length > 0
431
+ if args[0].is_a? Fixnum
432
+ @code = args.shift
433
+ super(OCI8.error_message(@code).gsub('%s') {|s| args.empty? ? '%s' : args.shift})
434
+ @sql = nil
435
+ @parse_error_offset = nil
436
+ else
437
+ msg, @code, @sql, @parse_error_offset = args
438
+ super(msg)
439
+ end
440
+ else
441
+ super()
442
+ end
443
+ end
444
+ end
445
+
385
446
  class OraDate
386
447
 
387
448
  # Returns a Time object which denotes self.
@@ -122,7 +122,7 @@ class OCI8
122
122
  # oraver = OCI8::OracleVersion.new('11.2.0.3')
123
123
  # oraver.to_s # => '11.2.0.3.0'
124
124
  #
125
- # @return [Integer]
125
+ # @return [String]
126
126
  def to_s
127
127
  format('%d.%d.%d.%d.%d', @major, @minor, @update, @patch, @port_update)
128
128
  end
@@ -1,26 +1,30 @@
1
1
  # properties.rb -- implements OCI8.properties
2
2
  #
3
- # Copyright (C) 2010-2012 KUBO Takehiro <kubo@jiubao.org>
3
+ # Copyright (C) 2010-2013 KUBO Takehiro <kubo@jiubao.org>
4
4
 
5
5
  #
6
6
  class OCI8
7
7
 
8
+ # @private
8
9
  @@properties = {
9
10
  :length_semantics => :byte,
10
11
  :bind_string_as_nchar => false,
11
- :float_conversion_type => :ruby,
12
+ :float_conversion_type => OCI8.__get_prop(1) ? :ruby : :oracle,
12
13
  :statement_cache_size => 0,
14
+ :events_mode => ((OCI8.__get_prop(2) & 4) != 0) # 4 <- OCI_EVENTS in oci.h
13
15
  }
14
16
 
15
17
  if OCI8.oracle_client_version < OCI8::ORAVER_9_2
16
18
  @@properties[:statement_cache_size] = nil
17
19
  end
18
20
 
21
+ # @private
19
22
  def @@properties.[](name)
20
23
  raise IndexError, "No such property name: #{name}" unless @@properties.has_key?(name)
21
24
  super(name)
22
25
  end
23
26
 
27
+ # @private
24
28
  def @@properties.[]=(name, val)
25
29
  raise IndexError, "No such property name: #{name}" unless @@properties.has_key?(name)
26
30
  case name
@@ -31,23 +35,31 @@ class OCI8
31
35
  when :bind_string_as_nchar
32
36
  val = val ? true : false
33
37
  when :float_conversion_type
34
- # handled by native code in oci8lib_xx.so.
35
- OCI8.__set_property(name, val)
38
+ case val
39
+ when :ruby
40
+ OCI8.__set_prop(1, true)
41
+ when :oracle
42
+ OCI8.__set_prop(1, false)
43
+ else
44
+ raise ArgumentError, "float_conversion_type's value should be either :ruby or :oracle."
45
+ end
36
46
  when :statement_cache_size
37
47
  if OCI8.oracle_client_version < OCI8::ORAVER_9_2
38
48
  raise RuntimeError, ":statement_cache_size is disabled on Oracle 9iR1 client."
39
49
  end
40
50
  val = val.to_i
41
51
  raise ArgumentError, "The property value for :statement_cache_size must not be negative." if val < 0
52
+ when :events_mode
53
+ val = val ? true : false
54
+ if val
55
+ OCI8.__set_prop(2, OCI8.__get_prop(2) | 4) # set OCI_EVENTS
56
+ else
57
+ OCI8.__set_prop(2, OCI8.__get_prop(2) & ~4) # unset OCI_EVENTS
58
+ end
42
59
  end
43
60
  super(name, val)
44
61
  end
45
62
 
46
- # call-seq:
47
- # OCI8.properties -> a customized Hash
48
- #
49
- # (new in 2.0.5)
50
- #
51
63
  # Returns a Hash which ruby-oci8 global settings.
52
64
  # The hash's setter and getter methods are customized to check
53
65
  # property names and values.
@@ -63,19 +75,20 @@ class OCI8
63
75
  # Supported properties are listed below:
64
76
  #
65
77
  # [:length_semantics]
66
- # (new in 2.1.0)
67
78
  #
68
79
  # +:char+ when Oracle character length is counted by the number of characters.
69
80
  # +:byte+ when it is counted by the number of bytes.
70
81
  # The default setting is +:byte+ because +:char+ causes unexpected behaviour on
71
82
  # Oracle 9i.
83
+ #
84
+ # *Since:* 2.1.0
72
85
  #
73
86
  # [:bind_string_as_nchar]
87
+ #
74
88
  # +true+ when string bind variables are bound as NCHAR,
75
89
  # otherwise +false+. The default value is +false+.
76
90
  #
77
91
  # [:float_conversion_type]
78
- # (new in 2.1.0)
79
92
  #
80
93
  # +:ruby+ when Oracle decimal numbers are converted to ruby Float values
81
94
  # same as Float#to_s does. (default)
@@ -85,14 +98,35 @@ class OCI8
85
98
  # the Oracle function OCINumberToReal() makes a string representation
86
99
  # 15.700000000000001 by Float#to_s.
87
100
  # See: http://rubyforge.org/forum/forum.php?thread_id=50030&forum_id=1078
101
+ #
102
+ # *Since:* 2.1.0
88
103
  #
89
104
  # [:statement_cache_size]
90
- # (new in 2.1.1)
91
105
  #
92
106
  # The statement cache size per each session. The default size is 0, which
93
107
  # means no statement cache, since 2.1.2. It was 20 in 2.1.1.
94
108
  # This feature is available on Oracle 9iR2 or later.
95
109
  # See: http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci09adv.htm#i471377
110
+ #
111
+ # *Since:* 2.1.1
112
+ #
113
+ # [:events_mode]
114
+ #
115
+ # +true+ when Fast Application Notification (FAN) Support is enabled.
116
+ # +false+ when it is disabled. The default value is +false+.
117
+ # This corresponds to {http://php.net/manual/en/oci8.configuration.php#ini.oci8.events +oci8.events+ in PHP}.
118
+ #
119
+ # This parameter can be changed only when no OCI methods are called.
120
+ #
121
+ # require 'oci8'
122
+ # OCI8.properties[:events_mode] = true # works fine.
123
+ # ... call some OCI methods ...
124
+ # OCI8.properties[:events_mode] = true # raises a runtime error.
125
+ #
126
+ # *Since:* 2.1.4
127
+ #
128
+ # @return [a customized Hash]
129
+ # @since 2.0.5
96
130
  #
97
131
  def self.properties
98
132
  @@properties
@@ -75,6 +75,22 @@ class TestCLob < Test::Unit::TestCase
75
75
  lob.close
76
76
  end
77
77
 
78
+ # https://github.com/kubo/ruby-oci8/issues/20
79
+ def test_github_issue_20
80
+ lob1 = OCI8::CLOB.new(@conn, ' ' * (1024 * 1024))
81
+ begin
82
+ lob2 = OCI8::CLOB.new(@conn, ' ' * (128 * 1024 * 1024))
83
+ rescue OCIError
84
+ raise if $!.code != 24817
85
+ # ORA-24817: Unable to allocate the given chunk for current lob operation
86
+ GC.start
87
+ # allocate smaller size
88
+ lob2 = OCI8::CLOB.new(@conn, ' ' * (16 * 1024 * 1024))
89
+ end
90
+ lob1 = nil # lob1's value will be freed in GC.
91
+ lob2.read # GC must run here to reproduce the issue.
92
+ end
93
+
78
94
  def teardown
79
95
  drop_table('test_table')
80
96
  @conn.logoff
@@ -25,7 +25,7 @@ STORAGE (
25
25
  MAXEXTENTS UNLIMITED
26
26
  PCTINCREASE 0)
27
27
  EOS
28
- ascii_8bit = Encoding.find('ASCII-8BIT')
28
+ ascii_8bit = "\xab\xcd".force_encoding('ASCII-8BIT')
29
29
  @conn.exec(<<EOS)
30
30
  INSERT INTO test_table VALUES ('abcd', 'abcd', 'abcd', 'abcd', 'abcd', 'abcd', 'abcd')
31
31
  EOS
@@ -34,16 +34,16 @@ EOS
34
34
  assert_equal(OCI8.encoding, row[0].encoding);
35
35
  assert_equal('abcd', row[1], 'VARCHAR2(10)')
36
36
  assert_equal(OCI8.encoding, row[1].encoding);
37
- assert_equal("\xab\xcd", row[2], 'RAW(10)')
38
- assert_equal(ascii_8bit, row[2].encoding);
39
- assert_equal("\xab\xcd", row[3], 'LONG RAW')
40
- assert_equal(ascii_8bit, row[3].encoding);
37
+ assert_equal(ascii_8bit, row[2], 'RAW(10)')
38
+ assert_equal(ascii_8bit.encoding, row[2].encoding);
39
+ assert_equal(ascii_8bit, row[3], 'LONG RAW')
40
+ assert_equal(ascii_8bit.encoding, row[3].encoding);
41
41
  assert_equal('abcd', (data = row[4].read), 'CLOB')
42
42
  assert_equal(OCI8.encoding, data.encoding);
43
43
  assert_equal('abcd', (data = row[5].read), 'NCLOB')
44
44
  assert_equal(OCI8.encoding, data.encoding);
45
- assert_equal("\xab\xcd", (data = row[6].read), 'BLOB')
46
- assert_equal(ascii_8bit, data.encoding);
45
+ assert_equal(ascii_8bit, (data = row[6].read), 'BLOB')
46
+ assert_equal(ascii_8bit.encoding, data.encoding);
47
47
 
48
48
  if OCI8.encoding.name == "UTF-8" and ['WE8ISO8859P1', 'WE8ISO8859P15', 'AL32UTF8', 'UTF8'].include? @conn.database_charset_name
49
49
  utf_8 = "\u00A1\u00A2\u00A3\u00A5\u00A7\u00A9"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.1.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-11 00:00:00.000000000 Z
12
+ date: 2013-01-06 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available
15
15
  with Oracle8, Oracle8i, Oracle9i, Oracle10g and Oracle Instant Client.
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  version: '0'
136
136
  requirements: []
137
137
  rubyforge_project: ruby-oci8
138
- rubygems_version: 1.8.23
138
+ rubygems_version: 1.8.11
139
139
  signing_key:
140
140
  specification_version: 3
141
141
  summary: Ruby interface for Oracle using OCI8 API