ruby-oci8 2.1.5 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -124,6 +124,7 @@ static VALUE attr_get_common(int argc, VALUE *argv, VALUE self, enum datatype da
124
124
  oci8_base_t *base = DATA_PTR(self);
125
125
  VALUE attr_type;
126
126
  VALUE strict;
127
+ VALUE args[6];
127
128
  union {
128
129
  ub1 ub1val;
129
130
  ub2 ub2val;
@@ -140,6 +141,10 @@ static VALUE attr_get_common(int argc, VALUE *argv, VALUE self, enum datatype da
140
141
  ub4 size = 0;
141
142
  sword rv;
142
143
 
144
+ if (base->type == 0) {
145
+ return Qnil;
146
+ }
147
+
143
148
  v.ub8val = MAGIC_NUMBER;
144
149
  rb_scan_args(argc, argv, "11", &attr_type, &strict);
145
150
  if (argc == 1) {
@@ -193,13 +198,13 @@ static VALUE attr_get_common(int argc, VALUE *argv, VALUE self, enum datatype da
193
198
  case DATATYPE_ORADATE:
194
199
  if (NIL_P(cOraDate))
195
200
  cOraDate = rb_eval_string("OraDate");
196
- return rb_funcall(cOraDate, oci8_id_new, 6,
197
- INT2FIX((v.ub1ptr[0] - 100) * 100 + (v.ub1ptr[1] - 100)),
198
- INT2FIX(v.ub1ptr[2]),
199
- INT2FIX(v.ub1ptr[3]),
200
- INT2FIX(v.ub1ptr[4] - 1),
201
- INT2FIX(v.ub1ptr[5] - 1),
202
- INT2FIX(v.ub1ptr[6] - 1));
201
+ args[0] = INT2FIX((v.ub1ptr[0] - 100) * 100 + (v.ub1ptr[1] - 100));
202
+ args[1] = INT2FIX(v.ub1ptr[2]);
203
+ args[2] = INT2FIX(v.ub1ptr[3]);
204
+ args[3] = INT2FIX(v.ub1ptr[4] - 1);
205
+ args[4] = INT2FIX(v.ub1ptr[5] - 1);
206
+ args[5] = INT2FIX(v.ub1ptr[6] - 1);
207
+ return rb_class_new_instance(6, args, cOraDate);
203
208
  }
204
209
  return Qnil;
205
210
  }
@@ -334,8 +334,9 @@ Backtrace:
334
334
  #{$!.backtrace.join("\n ")}
335
335
  ---------------------------------------------------
336
336
  See:
337
- * http://ruby-oci8.rubyforge.org/#{lang}/HowToInstall.html
338
- * http://ruby-oci8.rubyforge.org/#{lang}/ReportInstallProblem.html
337
+ * http://ruby-oci8.rubyforge.org/en/file.install-full-client.html for Oracle full client
338
+ * http://ruby-oci8.rubyforge.org/en/file.install-instant-client.html for Oracle instant client
339
+ * http://ruby-oci8.rubyforge.org/en/file.report-installation-issue.html to report an issue.
339
340
 
340
341
  EOS
341
342
  exc = RuntimeError.new
@@ -391,7 +392,7 @@ EOS
391
392
  when /mswin32|cygwin|mingw32|bccwin32/
392
393
  oci_basename = 'oci'
393
394
  oci_glob_postfix = ''
394
- nls_data_basename = ['oraociei11', 'oraociicus11', 'oraociei10', 'oraociicus10']
395
+ nls_data_basename = ['oraociei*', 'oraociicus*']
395
396
  @@ld_envs = %w[PATH]
396
397
  so_ext = 'dll'
397
398
  check_proc = make_proc_to_check_cpu(is_32bit ? :i386 : :x86_64)
@@ -523,7 +524,7 @@ EOS
523
524
  if ld_path
524
525
  nls_data_ext ||= so_ext # nls_data_ext is same with so_ext by default.
525
526
  nls_data_basename.each do |basename|
526
- if File.exist?(File.join(ld_path, "#{basename}.#{nls_data_ext}"))
527
+ if Dir.glob(File.join(ld_path, "#{basename}.#{nls_data_ext}")).size > 0
527
528
  puts " #{file} looks like an instant client."
528
529
  return ld_path
529
530
  end
@@ -645,12 +646,13 @@ EOS
645
646
 
646
647
  def get_libs(lib_dir)
647
648
  case RUBY_PLATFORM
648
- when /cygwin/
649
+ when /cygwin|x64-mingw32/
650
+ regex = ([nil].pack('P').size == 8) ? / T (OCI\w+)/ : / T _(OCI\w+)/
649
651
  open("OCI.def", "w") do |f|
650
652
  f.puts("EXPORTS")
651
653
  open("|nm #{lib_dir}/MSVC/OCI.LIB") do |r|
652
654
  while line = r.gets
653
- f.puts($') if line =~ / T _/
655
+ f.puts($1) if regex =~ line
654
656
  end
655
657
  end
656
658
  end
@@ -61,7 +61,7 @@ static VALUE oci8_stmt_initialize(VALUE self, VALUE svc, VALUE sql)
61
61
  if (!NIL_P(sql) && oracle_client_version >= ORAVER_9_2) {
62
62
  OCI8SafeStringValue(sql);
63
63
 
64
- rv = OCIStmtPrepare2(svcctx->base.hp.svc, &stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT);
64
+ rv = OCIStmtPrepare2_nb(svcctx, svcctx->base.hp.svc, &stmt->base.hp.stmt, oci8_errhp, RSTRING_ORATEXT(sql), RSTRING_LEN(sql), NULL, 0, OCI_NTV_SYNTAX, OCI_DEFAULT);
65
65
  if (IS_OCI_ERROR(rv)) {
66
66
  chker2(rv, &svcctx->base);
67
67
  }
@@ -342,7 +342,7 @@ static void bind_stmt_init_elem(oci8_bind_t *obind, VALUE svc)
342
342
  ub4 idx = 0;
343
343
 
344
344
  do {
345
- oho[idx].obj = rb_funcall(cOCIStmt, oci8_id_new, 1, svc);
345
+ oho[idx].obj = rb_class_new_instance(1, &svc, cOCIStmt);
346
346
  h = DATA_PTR(oho[idx].obj);
347
347
  oho[idx].hp = h->hp.ptr;
348
348
  } while (++idx < obind->maxar_sz);
@@ -50,8 +50,6 @@ when 'ruby'
50
50
  # if it wasn't explicitly changed by the configure option --with-ruby-version.
51
51
  #
52
52
  case RUBY_VERSION
53
- when /^2\.0/
54
- so_basename += RUBY_VERSION.gsub(/\W/, '')
55
53
  when /^1\.9\.0/
56
54
  raise 'unsupported ruby version: 1.9.0'
57
55
  when /^1\.9/
@@ -59,20 +57,10 @@ when 'ruby'
59
57
  when /^1\.8/
60
58
  so_basename += '18'
61
59
  else
62
- raise 'unsupported ruby version: ' + RUBY_VERSION
60
+ so_basename += RUBY_VERSION.gsub(/\W/, '')
63
61
  end
64
62
  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
63
+ so_basename += 'rbx'
76
64
  when 'jruby'
77
65
  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."
78
66
  else
@@ -104,6 +92,8 @@ class OCI8
104
92
  ORAVER_10_2 = OCI8::OracleVersion.new(10, 2)
105
93
  # @private
106
94
  ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
95
+ # @private
96
+ ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
107
97
 
108
98
  # @private
109
99
  @@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
@@ -478,6 +478,8 @@ class OCI8
478
478
  elsif key.class == Class && key < OCI8::Object::Base
479
479
  param = @con.get_tdo_by_class(key)
480
480
  key = :named_type
481
+ elsif key == :named_type
482
+ param = @con.get_tdo_by_typename(param[:length])
481
483
  end
482
484
  when OCI8::Metadata::Base
483
485
  key = param.data_type
@@ -110,7 +110,7 @@ class OCI8
110
110
  Proc.new do |p|
111
111
  if p.charset_form == :nchar
112
112
  "NVARCHAR2(#{p.char_size})"
113
- elsif p.char_used?
113
+ elsif p.respond_to?(:char_used?) && p.char_used?
114
114
  "VARCHAR2(#{p.char_size} CHAR)"
115
115
  else
116
116
  "VARCHAR2(#{p.data_size})"
@@ -248,6 +248,12 @@ class OCI8
248
248
  "TIMESTAMP(#{fsprecision}) WITH LOCAL TIME ZONE"
249
249
  end
250
250
  end]
251
+ DATA_TYPE_MAP[245] = [:record,
252
+ Proc.new do |p|
253
+ "#{p.schema_name}.#{p.type_name}"
254
+ end]
255
+ DATA_TYPE_MAP[252] = [:boolean, "BOOLEAN"]
256
+ DATA_TYPE_MAP[266] = [:pls_integer, "PLS_INTEGER"]
251
257
 
252
258
  def __data_type # :nodoc:
253
259
  return @data_type if defined? @data_type
@@ -337,6 +343,9 @@ class OCI8
337
343
  #when 228; :sysfirst # OCI_TYPECODE_SYSFIRST
338
344
  #when 235; :syslast # OCI_TYPECODE_SYSLAST
339
345
  when 266; :pls_integer # OCI_TYPECODE_PLS_INTEGER
346
+ when 250; :record # OCI_TYPECODE_RECORD
347
+ when 251; :itable # OCI_TYPECODE_ITABLE
348
+ when 252; :boolean # OCI_TYPECODE_BOOLEAN
340
349
  end
341
350
  end
342
351
  end
@@ -632,6 +641,12 @@ class OCI8
632
641
  end
633
642
  private :list_subprograms
634
643
 
644
+ # package type list
645
+ def list_types # :nodoc:
646
+ __param(137) # OCI_ATTR_LIST_PKG_TYPES
647
+ end
648
+ private :list_types
649
+
635
650
  # Returns +true+ if the package subprograms have
636
651
  # {invoker's rights}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/subprograms.htm#i18574].
637
652
  # Otherwise, +false+.
@@ -647,6 +662,22 @@ class OCI8
647
662
  prog.instance_variable_set(:@is_standalone, false)
648
663
  end
649
664
  end
665
+
666
+ if OCI8.oracle_client_version < ORAVER_12_1
667
+ def types
668
+ raise "This version of the Oracle client does not support PL/SQL package type descriptions."
669
+ end
670
+ else
671
+ # Returns an array of types defined within the Package.
672
+ #
673
+ # @return [array of OCI8::Metadata::Type]
674
+ # @since 2.1.6
675
+ def types
676
+ @types ||= list_types.to_a.each do |type|
677
+ type.instance_variable_set(:@is_standalone, false)
678
+ end
679
+ end
680
+ end
650
681
  end
651
682
 
652
683
  # Information about types
@@ -851,6 +882,15 @@ class OCI8
851
882
  attr_get_string(OCI_ATTR_SUPERTYPE_NAME) if is_subtype?
852
883
  end
853
884
 
885
+ # Returns the package name if the type is a package type.
886
+ # Otherwise, +nil+.
887
+ #
888
+ # @return [String or nil]
889
+ # @since 2.1.6
890
+ def package_name
891
+ attr_get_string(12, false) # OCI_ATTR_PACKAGE_NAME
892
+ end
893
+
854
894
  # Returns attribute information of the type.
855
895
  #
856
896
  # @return [array of OCI8::Metadata::TypeAttr]
@@ -1199,6 +1239,7 @@ class OCI8
1199
1239
  # schema name of the synonym translation
1200
1240
  def schema_name
1201
1241
  @schema_name ||= attr_get_string(OCI_ATTR_SCHEMA_NAME)
1242
+ @schema_name.size == 0 ? nil : @schema_name
1202
1243
  end
1203
1244
 
1204
1245
  # object name of the synonym translation
@@ -1214,11 +1255,7 @@ class OCI8
1214
1255
 
1215
1256
  # full-qualified synonym translation name with schema, object and database link name.
1216
1257
  def translated_name
1217
- if link.nil?
1218
- schema_name + '.' + name
1219
- else
1220
- schema_name + '.' + name + '@' + link
1221
- end
1258
+ (schema_name ? schema_name + '.' : '') + name + (link ? '@' + link : '')
1222
1259
  end
1223
1260
 
1224
1261
  def inspect # :nodoc:
@@ -1487,10 +1524,21 @@ class OCI8
1487
1524
  end
1488
1525
 
1489
1526
  # Indicates whether an argument has a default
1527
+ #
1528
+ # @return [1 or 0]
1529
+ # @deprecated
1490
1530
  def has_default
1491
1531
  attr_get_ub1(OCI_ATTR_HAS_DEFAULT)
1492
1532
  end
1493
1533
 
1534
+ # Indicates whether an argument has a default
1535
+ #
1536
+ # @return [true or false]
1537
+ # @since 2.1.6
1538
+ def has_default?
1539
+ __boolean(OCI_ATTR_HAS_DEFAULT)
1540
+ end
1541
+
1494
1542
  # The list of arguments at the next level (when the argument is
1495
1543
  # of a record or table type).
1496
1544
  def list_arguments
@@ -1648,8 +1696,9 @@ class OCI8
1648
1696
  #when OCI_LTYPE_TABLE_ALIAS; offset = ?
1649
1697
  #when OCI_LTYPE_VARIABLE_TYPE; offset = ?
1650
1698
  #when OCI_LTYPE_NAME_VALUE; offset = ?
1699
+ when 15; offset = 0 # OCI_LTYPE_PACKAGE_TYPE
1651
1700
  else
1652
- raise NotImplementedError, "unsupported list type #{list.ltype}"
1701
+ raise NotImplementedError, "unsupported list type #{ltype}"
1653
1702
  end
1654
1703
  ary = []
1655
1704
  0.upto(num_params - 1) do |i|
@@ -1994,7 +2043,13 @@ class OCI8
1994
2043
  # @param [String] object_name
1995
2044
  # @return [a subclass of OCI8::Metadata::Base]
1996
2045
  def describe_any(object_name)
1997
- __describe(object_name, OCI8::Metadata::Unknown, true)
2046
+ if /^PUBLIC\.(.*)/i =~ object_name
2047
+ md = __describe($1, OCI8::Metadata::Unknown, true)
2048
+ raise OCIError.new(4043, object_name) if md.obj_schema != 'PUBLIC'
2049
+ md
2050
+ else
2051
+ __describe(object_name, OCI8::Metadata::Unknown, true)
2052
+ end
1998
2053
  end
1999
2054
  # Returns table or view information. If the name is a current schema's synonym
2000
2055
  # name or a public synonym name, it returns table or view information which
@@ -2066,7 +2121,13 @@ class OCI8
2066
2121
  # @param [String] synonym_name
2067
2122
  # @return [OCI8::Metadata::Synonym]
2068
2123
  def describe_synonym(synonym_name, check_public_also = true)
2069
- __describe(synonym_name, OCI8::Metadata::Synonym, check_public_also)
2124
+ if /^PUBLIC\.(.*)/i =~ synonym_name
2125
+ md = __describe($1, OCI8::Metadata::Synonym, true)
2126
+ raise OCIError.new(4043, synonym_name) if md.obj_schema != 'PUBLIC'
2127
+ md
2128
+ else
2129
+ __describe(synonym_name, OCI8::Metadata::Synonym, check_public_also)
2130
+ end
2070
2131
  end
2071
2132
  # Returns sequence information
2072
2133
  #
@@ -71,6 +71,29 @@ EOS
71
71
  OCI8::TDO.new(self, metadata, klass)
72
72
  end
73
73
 
74
+ # Returns the type descriptor object which correspond to the given type name.
75
+ #
76
+ # @param [String] typename
77
+ # @return [OCI8::TDO]
78
+ #
79
+ # @private
80
+ def get_tdo_by_typename(typename)
81
+ tdo = @name_to_tdo && @name_to_tdo[typename]
82
+ return tdo if tdo
83
+
84
+ metadata = describe_any(typename)
85
+ if metadata.is_a? OCI8::Metadata::Synonym
86
+ metadata = describe_any(metadata.translated_name)
87
+ end
88
+ unless metadata.is_a? OCI8::Metadata::Type
89
+ raise "unknown typename #{typename}"
90
+ end
91
+ tdo = get_tdo_by_metadata(metadata)
92
+
93
+ @name_to_tdo[typename] = tdo
94
+ tdo
95
+ end
96
+
74
97
  # A helper class to bind arguments.
75
98
  #
76
99
  # @private
@@ -57,7 +57,7 @@ EOS
57
57
  if so_vers[0] < '2.0.0'
58
58
  s.required_ruby_version = "~> #{so_vermin}"
59
59
  else
60
- s.required_ruby_version = "= #{so_vermin}"
60
+ s.required_ruby_version = "~> #{so_vermin}.0"
61
61
  end
62
62
  else
63
63
  puts "Binary gem for ruby #{so_vers.join(', ')}"
@@ -18,6 +18,21 @@ $lobreadnum = 256 # counts in charactors
18
18
 
19
19
  # don't modify below.
20
20
 
21
+ begin
22
+ require 'minitest/autorun'
23
+ Minitest = MiniTest unless defined? Minitest
24
+ Minitest::Test = Minitest::Unit::TestCase unless defined? Minitest::Test
25
+ rescue LoadError
26
+ require 'test/unit'
27
+ module Minitest
28
+ Test = ::Test::Unit::TestCase
29
+ Assertions = ::Test::Unit::Assertions
30
+ module Assertions
31
+ alias refute_nil assert_not_nil
32
+ end
33
+ end
34
+ end
35
+
21
36
  # $oracle_server_version: database compatible level of the Oracle server.
22
37
  # $oracle_client_version: Oracle client library version for which oci8 is compiled.
23
38
  # $oracle_version: lower value of $oracle_server_version and $oracle_client_version.
@@ -108,77 +123,72 @@ def convert_to_datetime(year, month, day, hour, minute, sec, subsec, timezone)
108
123
  end
109
124
  end
110
125
 
111
- module Test
112
- module Unit
113
- class TestCase
126
+ class Minitest::Test
114
127
 
115
- def get_oci8_connection()
116
- OCI8.new($dbuser, $dbpass, $dbname)
128
+ def get_oci8_connection()
129
+ OCI8.new($dbuser, $dbpass, $dbname)
117
130
  rescue OCIError
118
- raise if $!.code != 12516 && $!.code != 12520
119
- # sleep a few second and try again if
120
- # the error code is ORA-12516 or ORA-12520.
121
- #
122
- # ORA-12516 - TNS:listener could not find available handler with
123
- # matching protocol stack
124
- # ORA-12520 - TNS:listener could not find available handler for
125
- # requested type of server
126
- #
127
- # Thanks to Christopher Jones.
128
- #
129
- # Ref: The Underground PHP and Oracle Manual (page 175 in vesion 1.4)
130
- # http://www.oracle.com/technology/tech/php/pdf/underground-php-oracle-manual.pdf
131
- #
132
- sleep(5)
133
- OCI8.new($dbuser, $dbpass, $dbname)
134
- end
131
+ raise if $!.code != 12516 && $!.code != 12520
132
+ # sleep a few second and try again if
133
+ # the error code is ORA-12516 or ORA-12520.
134
+ #
135
+ # ORA-12516 - TNS:listener could not find available handler with
136
+ # matching protocol stack
137
+ # ORA-12520 - TNS:listener could not find available handler for
138
+ # requested type of server
139
+ #
140
+ # Thanks to Christopher Jones.
141
+ #
142
+ # Ref: The Underground PHP and Oracle Manual (page 175 in vesion 1.4)
143
+ # http://www.oracle.com/technology/tech/php/pdf/underground-php-oracle-manual.pdf
144
+ #
145
+ sleep(5)
146
+ OCI8.new($dbuser, $dbpass, $dbname)
147
+ end
148
+
149
+ def get_dbi_connection()
150
+ DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
151
+ rescue DBI::DatabaseError
152
+ raise if $!.err != 12516 && $!.err != 12520
153
+ # same as get_oci8_connection()
154
+ sleep(5)
155
+ DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
156
+ end
135
157
 
136
- def get_dbi_connection()
137
- DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
158
+ def drop_table(table_name)
159
+ if $oracle_server_version < OCI8::ORAVER_10_1
160
+ # Oracle 8 - 9i
161
+ sql = "DROP TABLE #{table_name}"
162
+ else
163
+ # Oracle 10g -
164
+ sql = "DROP TABLE #{table_name} PURGE"
165
+ end
166
+
167
+ if defined? @conn
168
+ begin
169
+ @conn.exec(sql)
170
+ rescue OCIError
171
+ raise if $!.code != 942 # table or view does not exist
172
+ end
173
+ elsif instance_variable_get(:@dbh)
174
+ begin
175
+ @dbh.do(sql)
138
176
  rescue DBI::DatabaseError
139
- raise if $!.err != 12516 && $!.err != 12520
140
- # same as get_oci8_connection()
141
- sleep(5)
142
- DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
177
+ raise if $!.err != 942 # table or view does not exist
143
178
  end
179
+ end
180
+ end # drop_table
144
181
 
145
- def drop_table(table_name)
146
- if $oracle_server_version < OCI8::ORAVER_10_1
147
- # Oracle 8 - 9i
148
- sql = "DROP TABLE #{table_name}"
149
- else
150
- # Oracle 10g -
151
- sql = "DROP TABLE #{table_name} PURGE"
152
- end
153
-
154
- if defined? @conn
155
- begin
156
- @conn.exec(sql)
157
- rescue OCIError
158
- raise if $!.code != 942 # table or view does not exist
159
- end
160
- elsif instance_variable_get(:@dbh)
161
- begin
162
- @dbh.do(sql)
163
- rescue DBI::DatabaseError
164
- raise if $!.err != 942 # table or view does not exist
165
- end
166
- end
167
- end # drop_table
168
-
169
- def drop_type(type_name)
170
- begin
171
- @conn.exec("DROP TYPE BODY #{type_name}")
172
- rescue OCIError
173
- raise if $!.code != 4043
174
- end
175
- begin
176
- @conn.exec("DROP TYPE #{type_name}")
177
- rescue OCIError
178
- raise if $!.code != 4043
179
- end
180
- end # drop_type
182
+ def drop_type(type_name)
183
+ begin
184
+ @conn.exec("DROP TYPE BODY #{type_name}")
185
+ rescue OCIError
186
+ raise if $!.code != 4043
181
187
  end
182
- end
188
+ begin
189
+ @conn.exec("DROP TYPE #{type_name}")
190
+ rescue OCIError
191
+ raise if $!.code != 4043
192
+ end
193
+ end # drop_type
183
194
  end
184
-