From nobody at rubyforge.org Sun Dec 2 10:17:05 2012 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 2 Dec 2012 10:17:05 +0000 (UTC) Subject: [ruby-oci8-commit] [543] trunk/ruby-oci8: fix to pass tests with ruby 2.0.0 preview2. Message-ID: <20121202101705.BC4302E076@rubyforge.org> Revision: 543 Author: kubo Date: 2012-12-02 10:17:05 +0000 (Sun, 02 Dec 2012) Log Message: ----------- fix to pass tests with ruby 2.0.0 preview2. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/test/test_encoding.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2012-11-11 13:05:57 UTC (rev 542) +++ trunk/ruby-oci8/ChangeLog 2012-12-02 10:17:05 UTC (rev 543) @@ -1,3 +1,6 @@ +2012-12-02 KUBO Takehiro + * test/test_encoding.rb: fix to pass tests with ruby 2.0.0 preview2. + 2012-11-11 KUBO Takehiro * ext/oci8/lob.c: use OCILobLocatorAssign_nb (non-blocking version) instead of OCILobLocatorAssign (blocking version). Modified: trunk/ruby-oci8/test/test_encoding.rb =================================================================== --- trunk/ruby-oci8/test/test_encoding.rb 2012-11-11 13:05:57 UTC (rev 542) +++ trunk/ruby-oci8/test/test_encoding.rb 2012-12-02 10:17:05 UTC (rev 543) @@ -25,7 +25,7 @@ MAXEXTENTS UNLIMITED PCTINCREASE 0) EOS - ascii_8bit = Encoding.find('ASCII-8BIT') + ascii_8bit = "\xab\xcd".force_encoding('ASCII-8BIT') @conn.exec(< Revision: 544 Author: kubo Date: 2012-12-03 10:42:33 +0000 (Mon, 03 Dec 2012) Log Message: ----------- add a script encoding magic comment for ruby 2.0.0 preview2. Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/oraconf.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2012-12-02 10:17:05 UTC (rev 543) +++ trunk/ruby-oci8/ChangeLog 2012-12-03 10:42:33 UTC (rev 544) @@ -1,3 +1,7 @@ +2012-12-03 KUBO Takehiro + * ext/oci8/oraconf.rb: add a script encoding magic comment for ruby 2.0.0 preview2. + (github issue #25 reported by aboltart) + 2012-12-02 KUBO Takehiro * test/test_encoding.rb: fix to pass tests with ruby 2.0.0 preview2. Modified: trunk/ruby-oci8/ext/oci8/oraconf.rb =================================================================== --- trunk/ruby-oci8/ext/oci8/oraconf.rb 2012-12-02 10:17:05 UTC (rev 543) +++ trunk/ruby-oci8/ext/oci8/oraconf.rb 2012-12-03 10:42:33 UTC (rev 544) @@ -1,3 +1,4 @@ +# coding: ascii require 'mkmf' # compatibility for ruby-1.9 From nobody at rubyforge.org Sun Dec 16 02:55:19 2012 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 16 Dec 2012 02:55:19 +0000 (UTC) Subject: [ruby-oci8-commit] [545] trunk/ruby-oci8: Use RUBY_VERSION instead of RbConfig::CONFIG[' ruby_version'] to know the ruby ABI version. Message-ID: <20121216025519.D0F652E076@rubyforge.org> Revision: 545 Author: kubo Date: 2012-12-16 02:55:19 +0000 (Sun, 16 Dec 2012) Log Message: ----------- Use RUBY_VERSION instead of RbConfig::CONFIG['ruby_version'] to know the ruby ABI version. The latter may be changed by the configure option --with-ruby-version. (github issue #24 reported by suhrawardi) Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/extconf.rb trunk/ruby-oci8/lib/oci8.rb.in Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2012-12-03 10:42:33 UTC (rev 544) +++ trunk/ruby-oci8/ChangeLog 2012-12-16 02:55:19 UTC (rev 545) @@ -1,3 +1,9 @@ +2012-12-16 KUBO Takehiro + * ext/oci8/extconf.rb, lib/oci8.rb.in: use RUBY_VERSION instead of + RbConfig::CONFIG['ruby_version'] to know the ruby ABI version. + The latter may be changed by the configure option --with-ruby-version. + (github issue #24 reported by suhrawardi) + 2012-12-03 KUBO Takehiro * ext/oci8/oraconf.rb: add a script encoding magic comment for ruby 2.0.0 preview2. (github issue #25 reported by aboltart) Modified: trunk/ruby-oci8/ext/oci8/extconf.rb =================================================================== --- trunk/ruby-oci8/ext/oci8/extconf.rb 2012-12-03 10:42:33 UTC (rev 544) +++ trunk/ruby-oci8/ext/oci8/extconf.rb 2012-12-16 02:55:19 UTC (rev 545) @@ -135,11 +135,39 @@ so_basename = 'oci8lib_' if ruby_engine == 'ruby' - # Config::CONFIG["ruby_version"] indicates the ruby API version. - # 1.8 - ruby 1.8.x - # 1.9.1 - ruby 1.9.1, 1.9.2 - # 2.0.0 - ruby 2.0.0 - so_basename += RbConfig::CONFIG["ruby_version"].gsub(/\W/, '') + # The extension library name includes the ruby ABI (application binary interface) + # version. It is for binary gems which contain more than one extension library + # and use correct one depending on the ABI version. + # + # ruby version | ABI version + # --------------+-------------- + # 1.8.6 | 1.8 + # 1.8.7 | 1.8 + # --------------+-------------- + # 1.9.0 | 1.9.0 + # 1.9.1 | 1.9.1 + # 1.9.2 | 1.9.1 + # 1.9.3 | 1.9.1 + # --------------+-------------- + # 2.0.0 | 2.0.0 + # 2.0.1 | 2.0.1 (See: [ruby-core:49578]) + # ... | ... + # + # Note: The ruby ABI version is same with RbConfig::CONFIG['ruby_version'] + # if it wasn't explicitly changed by the configure option --with-ruby-version. + # + case RUBY_VERSION + when /^2\.0/ + so_basename += RUBY_VERSION.gsub(/\W/, '') + when /^1\.9\.0/ + raise 'unsupported ruby version: 1.9.0' + when /^1\.9/ + so_basename += '191' + when /^1\.8/ + so_basename += '18' + else + raise 'unsupported ruby version: ' + RUBY_VERSION + end else so_basename += ruby_engine end Modified: trunk/ruby-oci8/lib/oci8.rb.in =================================================================== --- trunk/ruby-oci8/lib/oci8.rb.in 2012-12-03 10:42:33 UTC (rev 544) +++ trunk/ruby-oci8/lib/oci8.rb.in 2012-12-16 02:55:19 UTC (rev 545) @@ -27,13 +27,32 @@ so_basename = 'oci8lib_' if ruby_engine == 'ruby' - # The suffix number indicates the ruby API version. - # 1.8 - ruby 1.8.x - # 1.9.1 - ruby 1.9.1, 1.9.2 - # 2.0.0 - ruby 2.0.0-dev at the present time. + # The extension library name includes the ruby ABI (application binary interface) + # version. It is for binary gems which contain more than one extension library + # and use correct one depending on the ABI version. + # + # ruby version | ABI version + # --------------+-------------- + # 1.8.6 | 1.8 + # 1.8.7 | 1.8 + # --------------+-------------- + # 1.9.0 | 1.9.0 + # 1.9.1 | 1.9.1 + # 1.9.2 | 1.9.1 + # 1.9.3 | 1.9.1 + # --------------+-------------- + # 2.0.0 | 2.0.0 + # 2.0.1 | 2.0.1 (See: [ruby-core:49578]) + # ... | ... + # + # Note: The ruby ABI version is same with RbConfig::CONFIG['ruby_version'] + # if it wasn't explicitly changed by the configure option --with-ruby-version. + # case RUBY_VERSION when /^2\.0/ - so_basename += '200' + so_basename += RUBY_VERSION.gsub(/\W/, '') + when /^1\.9\.0/ + raise 'unsupported ruby version: 1.9.0' when /^1\.9/ so_basename += '191' when /^1\.8/ From nobody at rubyforge.org Tue Dec 18 12:12:11 2012 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Tue, 18 Dec 2012 12:12:11 +0000 (UTC) Subject: [ruby-oci8-commit] [546] trunk/ruby-oci8: fix OCI8. describe_table not to follow synonyms until stack overflow. Message-ID: <20121218121211.E10022E079@rubyforge.org> Revision: 546 Author: kubo Date: 2012-12-18 12:12:11 +0000 (Tue, 18 Dec 2012) Log Message: ----------- fix OCI8.describe_table not to follow synonyms until stack overflow. Now the recursive level is limited to 20. (github issue #26 reported by Brian Henderson) Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/error.c trunk/ruby-oci8/lib/oci8/metadata.rb trunk/ruby-oci8/lib/oci8/oci8.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2012-12-16 02:55:19 UTC (rev 545) +++ trunk/ruby-oci8/ChangeLog 2012-12-18 12:12:11 UTC (rev 546) @@ -1,3 +1,11 @@ +2012-12-18 KUBO Takehiro + * ext/oci8/error.c, lib/oci8/oci8.rb: change the OCIError constructor to + accept an Oracle error code as the first parameter and create a message + which depends on NLS_LANG. + * lib/oci8/metadata.rb: fix OCI8.describe_table not to follow synonyms + until stack overflow. Now the recursive level is limited to 20. + (github issue #26 reported by Brian Henderson) + 2012-12-16 KUBO Takehiro * ext/oci8/extconf.rb, lib/oci8.rb.in: use RUBY_VERSION instead of RbConfig::CONFIG['ruby_version'] to know the ruby ABI version. Modified: trunk/ruby-oci8/ext/oci8/error.c =================================================================== --- trunk/ruby-oci8/ext/oci8/error.c 2012-12-16 02:55:19 UTC (rev 545) +++ trunk/ruby-oci8/ext/oci8/error.c 2012-12-18 12:12:11 UTC (rev 546) @@ -160,31 +160,6 @@ return exc; } -/* - * call-seq: - * initialize(message, code = nil, sql = nil, parse_error_offset = nil) - * - * Creates a new OCIError object. - * - * @example - * OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1) - * # => # - */ -static VALUE oci8_error_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE msg; - VALUE code; - VALUE sql; - VALUE parse_error_offset; - - rb_scan_args(argc, argv, "04", &msg, &code, &sql, &parse_error_offset); - rb_call_super(argc > 1 ? 1 : argc, argv); - rb_ivar_set(self, oci8_id_at_code, code); - rb_ivar_set(self, oci8_id_at_sql, sql); - rb_ivar_set(self, oci8_id_at_parse_error_offset, parse_error_offset); - return Qnil; -} - sb4 oci8_get_error_code(OCIError *errhp) { sb4 errcode = -1; @@ -214,8 +189,6 @@ eOCIContinue = rb_define_class("OCIContinue", eOCIException); eOCISuccessWithInfo = rb_define_class("OCISuccessWithInfo", eOCIError); - rb_define_method(eOCIError, "initialize", oci8_error_initialize, -1); - /* * @attr_reader [Integer] code error code */ Modified: trunk/ruby-oci8/lib/oci8/metadata.rb =================================================================== --- trunk/ruby-oci8/lib/oci8/metadata.rb 2012-12-16 02:55:19 UTC (rev 545) +++ trunk/ruby-oci8/lib/oci8/metadata.rb 2012-12-18 12:12:11 UTC (rev 546) @@ -2007,15 +2007,19 @@ __describe(table_name, OCI8::Metadata::Table, false) else # check tables, views, synonyms and public synonyms. - metadata = __describe(table_name, OCI8::Metadata::Unknown, true) - case metadata - when OCI8::Metadata::Table, OCI8::Metadata::View - metadata - when OCI8::Metadata::Synonym - describe_table(metadata.translated_name) - else - raise OCIError.new("ORA-04043: object #{table_name} does not exist", 4043) + recursive_level = 20 + recursive_level.times do + metadata = __describe(table_name, OCI8::Metadata::Unknown, true) + case metadata + when OCI8::Metadata::Table, OCI8::Metadata::View + return metadata + when OCI8::Metadata::Synonym + table_name = metadata.translated_name + else + raise OCIError.new(4043, table_name) # ORA-04043: object %s does not exist + end end + raise OCIError.new(36, recursive_level) # ORA-00036: maximum number of recursive SQL levels (%s) exceeded end end # returns a OCI8::Metadata::View in the current schema. Modified: trunk/ruby-oci8/lib/oci8/oci8.rb =================================================================== --- trunk/ruby-oci8/lib/oci8/oci8.rb 2012-12-16 02:55:19 UTC (rev 545) +++ trunk/ruby-oci8/lib/oci8/oci8.rb 2012-12-18 12:12:11 UTC (rev 546) @@ -382,6 +382,63 @@ end end +class OCIError + + # @overload initialize(message, error_code = nil, sql_stmt = nil, parse_error_offset = nil) + # Creates a new OCIError object with specified parameters. + # + # @param [String] message error message + # @param [Integer] error_code Oracle error code + # @param [String] sql_stmt SQL statement + # @param [Integer] parse_error_offset + # + # @example + # OCIError.new("ORA-00001: unique constraint (%s.%s) violated", 1, 'insert into table_name values (1)', ) + # # => # + # # + # "select sysdate" + # 923 + # 14 + # + # @overload initialize(error_code, *params) + # Creates a new OCIError object with the error message which corresponds to the specified + # Oracle error code. + # + # @param [Integer] error_code Oracle error code + # @param [String, ...] params parameters which replace '%s' + # + # @example + # # without parameters + # OCIError.new(4043) + # # When NLS_LANG=american_america.AL32UTF8 + # # => # + # # When NLS_LANG=german_germany.AL32UTF8 + # # => # + # + # # with one parameter + # OCIError.new(4043, 'table_name') + # # When NLS_LANG=american_america.AL32UTF8 + # # => # + # # When NLS_LANG=german_germany.AL32UTF8 + # # => # + # + def initialize(*args) + if args.length > 0 + if args[0].is_a? Fixnum + @code = args.shift + super(OCI8.error_message(@code).gsub('%s') {|s| args.empty? ? '%s' : args.shift}) + @sql = nil + @parse_error_offset = nil + else + msg, @code, @sql, @parse_error_offset = args + super(msg) + end + else + super() + end + end +end + class OraDate # Returns a Time object which denotes self. From nobody at rubyforge.org Sun Dec 23 11:47:17 2012 From: nobody at rubyforge.org (nobody at rubyforge.org) Date: Sun, 23 Dec 2012 11:47:17 +0000 (UTC) Subject: [ruby-oci8-commit] [547] trunk/ruby-oci8: Fix SEGV when a temporary LOB is freed when OCILobRead returns OCI_NEED_DATA . Message-ID: <20121223114717.293F12E083@rubyforge.org> Revision: 547 Author: kubo Date: 2012-12-23 11:47:16 +0000 (Sun, 23 Dec 2012) Log Message: ----------- Fix SEGV when a temporary LOB is freed when OCILobRead returns OCI_NEED_DATA. (github issue #20 reported by Edgars Beigarts) Modified Paths: -------------- trunk/ruby-oci8/ChangeLog trunk/ruby-oci8/ext/oci8/lob.c trunk/ruby-oci8/ext/oci8/oci8.h trunk/ruby-oci8/ext/oci8/oci8lib.c trunk/ruby-oci8/test/test_clob.rb Modified: trunk/ruby-oci8/ChangeLog =================================================================== --- trunk/ruby-oci8/ChangeLog 2012-12-18 12:12:11 UTC (rev 546) +++ trunk/ruby-oci8/ChangeLog 2012-12-23 11:47:16 UTC (rev 547) @@ -1,3 +1,8 @@ +2012-12-23 KUBO Takehiro + * ext/oci8/lob.c, ext/oci8/oci8.h, ext/oci8/oci8lib.c, test/test_clob.rb: + fix SEGV when a temporary LOB is freed when OCILobRead returns OCI_NEED_DATA. + (github issue #20 reported by Edgars Beigarts) + 2012-12-18 KUBO Takehiro * ext/oci8/error.c, lib/oci8/oci8.rb: change the OCIError constructor to accept an Oracle error code as the first parameter and create a message Modified: trunk/ruby-oci8/ext/oci8/lob.c =================================================================== --- trunk/ruby-oci8/ext/oci8/lob.c 2012-12-18 12:12:11 UTC (rev 546) +++ trunk/ruby-oci8/ext/oci8/lob.c 2012-12-23 11:47:16 UTC (rev 547) @@ -554,12 +554,24 @@ /* initialize buf in zeros everytime to check a nul characters. */ memset(buf, 0, sizeof(buf)); 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); - if (rv == OCI_ERROR && oci8_get_error_code(oci8_errhp) == 22289) { - /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */ - if (lob->state == S_BFILE_CLOSE) - continue; - } - if (rv != OCI_SUCCESS && rv != OCI_NEED_DATA) { + svcctx->suppress_free_temp_lobs = 0; + switch (rv) { + case OCI_SUCCESS: + break; + case OCI_NEED_DATA: + /* prevent OCILobFreeTemporary() from being called. + * See: https://github.com/kubo/ruby-oci8/issues/20 + */ + svcctx->suppress_free_temp_lobs = 1; + break; + case OCI_ERROR: + if (oci8_get_error_code(oci8_errhp) == 22289) { + /* ORA-22289: cannot perform FILEREAD operation on an unopened file or LOB */ + if (lob->state == S_BFILE_CLOSE) + continue; + } + /* FALLTHROUGH */ + default: chker2(rv, &svcctx->base); } Modified: trunk/ruby-oci8/ext/oci8/oci8.h =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8.h 2012-12-18 12:12:11 UTC (rev 546) +++ trunk/ruby-oci8/ext/oci8/oci8.h 2012-12-23 11:47:16 UTC (rev 547) @@ -361,6 +361,7 @@ rb_pid_t pid; unsigned char state; char is_autocommit; + char suppress_free_temp_lobs; #ifdef NATIVE_THREAD_WITH_GVL char non_blocking; #endif Modified: trunk/ruby-oci8/ext/oci8/oci8lib.c =================================================================== --- trunk/ruby-oci8/ext/oci8/oci8lib.c 2012-12-18 12:12:11 UTC (rev 546) +++ trunk/ruby-oci8/ext/oci8/oci8lib.c 2012-12-23 11:47:16 UTC (rev 547) @@ -229,44 +229,45 @@ /* ruby 1.9 */ sword oci8_call_without_gvl(oci8_svcctx_t *svcctx, void *(*func)(void *), void *data) { - oci8_temp_lob_t *lob; OCIError *errhp = oci8_errhp; if (!NIL_P(svcctx->executing_thread)) { rb_raise(rb_eRuntimeError /* FIXME */, "executing in another thread"); } - lob = svcctx->temp_lobs; - while (lob != NULL) { - oci8_temp_lob_t *lob_next = lob->next; + if (!svcctx->suppress_free_temp_lobs) { + oci8_temp_lob_t *lob = svcctx->temp_lobs; + while (lob != NULL) { + oci8_temp_lob_t *lob_next = lob->next; - if (svcctx->non_blocking) { - free_temp_lob_arg_t arg; - sword rv; + if (svcctx->non_blocking) { + free_temp_lob_arg_t arg; + sword rv; - arg.svcctx = svcctx; - arg.svchp = svcctx->base.hp.svc; - arg.errhp = errhp; - arg.lob = lob->lob; + arg.svcctx = svcctx; + arg.svchp = svcctx->base.hp.svc; + arg.errhp = errhp; + arg.lob = lob->lob; - svcctx->executing_thread = rb_thread_current(); + svcctx->executing_thread = rb_thread_current(); #ifdef HAVE_RB_THREAD_CALL_WITHOUT_GVL - rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx); + rv = (sword)(VALUE)rb_thread_call_without_gvl(free_temp_lob, &arg, oci8_unblock_func, svcctx); #else - rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx); + rv = (sword)rb_thread_blocking_region((VALUE(*)(void*))free_temp_lob, &arg, oci8_unblock_func, svcctx); #endif - if (rv == OCI_ERROR) { - if (oci8_get_error_code(errhp) == 1013) { - rb_raise(eOCIBreak, "Canceled by user request."); + if (rv == OCI_ERROR) { + if (oci8_get_error_code(errhp) == 1013) { + rb_raise(eOCIBreak, "Canceled by user request."); + } } + } else { + OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob); } - } else { - OCILobFreeTemporary(svcctx->base.hp.svc, errhp, lob->lob); + OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB); + + xfree(lob); + svcctx->temp_lobs = lob = lob_next; } - OCIDescriptorFree(lob->lob, OCI_DTYPE_LOB); - - xfree(lob); - svcctx->temp_lobs = lob = lob_next; } if (svcctx->non_blocking) { Modified: trunk/ruby-oci8/test/test_clob.rb =================================================================== --- trunk/ruby-oci8/test/test_clob.rb 2012-12-18 12:12:11 UTC (rev 546) +++ trunk/ruby-oci8/test/test_clob.rb 2012-12-23 11:47:16 UTC (rev 547) @@ -75,6 +75,15 @@ lob.close end + # https://github.com/kubo/ruby-oci8/issues/20 + def test_github_issue_20 + lob1 = OCI8::CLOB.new(@conn, ' ' * (1024 * 1024)) + lob2 = OCI8::CLOB.new(@conn, ' ' * (128 * 1024 * 1024)) + + lob1 = nil # lob1's value will be freed in GC. + lob2.read # GC must run here to reproduce the issue. + end + def teardown drop_table('test_table') @conn.logoff