ruby-oci8 2.2.0.2 → 2.2.12

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +1 -6
  3. data/ChangeLog +600 -0
  4. data/NEWS +426 -35
  5. data/README.md +27 -9
  6. data/dist-files +13 -2
  7. data/docs/bind-array-to-in_cond.md +38 -0
  8. data/docs/conflicts-local-connections-and-processes.md +98 -0
  9. data/docs/hanging-after-inactivity.md +63 -0
  10. data/docs/install-binary-package.md +15 -11
  11. data/docs/install-full-client.md +18 -21
  12. data/docs/install-instant-client.md +45 -27
  13. data/docs/install-on-osx.md +31 -117
  14. data/docs/ldap-auth-and-function-interposition.md +123 -0
  15. data/docs/number-type-mapping.md +79 -0
  16. data/docs/platform-specific-issues.md +17 -50
  17. data/docs/report-installation-issue.md +11 -8
  18. data/docs/timeout-parameters.md +94 -0
  19. data/ext/oci8/apiwrap.c.tmpl +2 -5
  20. data/ext/oci8/apiwrap.rb +6 -1
  21. data/ext/oci8/apiwrap.yml +39 -143
  22. data/ext/oci8/attr.c +4 -2
  23. data/ext/oci8/bind.c +421 -9
  24. data/ext/oci8/connection_pool.c +3 -3
  25. data/ext/oci8/encoding.c +5 -5
  26. data/ext/oci8/env.c +8 -2
  27. data/ext/oci8/error.c +24 -16
  28. data/ext/oci8/extconf.rb +35 -63
  29. data/ext/oci8/hook_funcs.c +274 -61
  30. data/ext/oci8/lob.c +31 -75
  31. data/ext/oci8/metadata.c +8 -6
  32. data/ext/oci8/object.c +119 -29
  33. data/ext/oci8/oci8.c +46 -133
  34. data/ext/oci8/oci8.h +40 -123
  35. data/ext/oci8/oci8lib.c +178 -46
  36. data/ext/oci8/ocihandle.c +37 -37
  37. data/ext/oci8/ocinumber.c +24 -35
  38. data/ext/oci8/oraconf.rb +168 -337
  39. data/ext/oci8/oradate.c +19 -19
  40. data/ext/oci8/plthook.h +10 -0
  41. data/ext/oci8/plthook_elf.c +433 -268
  42. data/ext/oci8/plthook_osx.c +40 -9
  43. data/ext/oci8/plthook_win32.c +16 -1
  44. data/ext/oci8/stmt.c +52 -17
  45. data/ext/oci8/win32.c +4 -22
  46. data/lib/oci8/bindtype.rb +10 -17
  47. data/lib/oci8/check_load_error.rb +57 -10
  48. data/lib/oci8/compat.rb +5 -1
  49. data/lib/oci8/connection_pool.rb +74 -3
  50. data/lib/oci8/cursor.rb +70 -31
  51. data/lib/oci8/metadata.rb +9 -1
  52. data/lib/oci8/object.rb +14 -1
  53. data/lib/oci8/oci8.rb +184 -58
  54. data/lib/oci8/ocihandle.rb +0 -16
  55. data/lib/oci8/oracle_version.rb +11 -1
  56. data/lib/oci8/properties.rb +55 -0
  57. data/lib/oci8/version.rb +1 -1
  58. data/lib/oci8.rb +48 -4
  59. data/lib/ruby-oci8.rb +1 -0
  60. data/pre-distclean.rb +1 -3
  61. data/ruby-oci8.gemspec +4 -9
  62. data/setup.rb +11 -2
  63. data/test/README.md +37 -0
  64. data/test/config.rb +8 -1
  65. data/test/setup_test_object.sql +42 -14
  66. data/test/setup_test_package.sql +59 -0
  67. data/test/test_all.rb +4 -0
  68. data/test/test_bind_array.rb +70 -0
  69. data/test/test_bind_boolean.rb +99 -0
  70. data/test/test_bind_integer.rb +47 -0
  71. data/test/test_break.rb +11 -9
  72. data/test/test_clob.rb +5 -17
  73. data/test/test_connstr.rb +142 -0
  74. data/test/test_datetime.rb +8 -3
  75. data/test/test_metadata.rb +2 -1
  76. data/test/test_object.rb +99 -18
  77. data/test/test_oci8.rb +170 -46
  78. data/test/test_oranumber.rb +12 -6
  79. data/test/test_package_type.rb +17 -3
  80. data/test/test_properties.rb +17 -0
  81. metadata +45 -55
  82. data/docs/osx-install-dev-tools.png +0 -0
  83. data/test/README +0 -42
@@ -13,6 +13,12 @@ class OCI8
13
13
  :statement_cache_size => 0,
14
14
  :events_mode => ((OCI8.__get_prop(2) & 4) != 0), # 4 <- OCI_EVENTS in oci.h
15
15
  :cancel_read_at_exit => false,
16
+ :tcp_connect_timeout => nil,
17
+ :connect_timeout => nil,
18
+ :send_timeout => nil,
19
+ :recv_timeout => nil,
20
+ :tcp_keepalive => false,
21
+ :tcp_keepalive_time => nil,
16
22
  }
17
23
 
18
24
  # @private
@@ -53,6 +59,19 @@ class OCI8
53
59
  when :cancel_read_at_exit
54
60
  val = val ? true : false
55
61
  OCI8.__set_prop(3, val)
62
+ when :tcp_connect_timeout, :connect_timeout, :send_timeout, :recv_timeout
63
+ if !val.nil?
64
+ val = val.to_i
65
+ raise ArgumentError, "The property value for :#{name} must be nil or a positive integer." if val <= 0
66
+ end
67
+ when :tcp_keepalive
68
+ val = val ? true : false
69
+ when :tcp_keepalive_time
70
+ if !val.nil?
71
+ val = val.to_i
72
+ raise ArgumentError, "The property value for :#{name} must be nil or a positive integer." if val <= 0
73
+ end
74
+ OCI8.__set_prop(4, val)
56
75
  end
57
76
  super(name, val)
58
77
  end
@@ -132,6 +151,42 @@ class OCI8
132
151
  #
133
152
  # *Since:* 2.1.8
134
153
  #
154
+ # [:tcp_connect_timeout]
155
+ #
156
+ # See {file:docs/timeout-parameters.md}
157
+ #
158
+ # *Since:* 2.2.2
159
+ #
160
+ # [:connect_timeout]
161
+ #
162
+ # See {file:docs/timeout-parameters.md}
163
+ #
164
+ # *Since:* 2.2.2
165
+ #
166
+ # [:send_timeout]
167
+ #
168
+ # See {file:docs/timeout-parameters.md}
169
+ #
170
+ # *Since:* 2.2.2
171
+ #
172
+ # [:recv_timeout]
173
+ #
174
+ # See {file:docs/timeout-parameters.md}
175
+ #
176
+ # *Since:* 2.2.2
177
+ #
178
+ # [:tcp_keepalive]
179
+ #
180
+ # See {file:docs/hanging-after-inactivity.md}
181
+ #
182
+ # *Since:* 2.2.4
183
+ #
184
+ # [:tcp_keepalive_time]
185
+ #
186
+ # See {file:docs/hanging-after-inactivity.md}
187
+ #
188
+ # *Since:* 2.2.4
189
+ #
135
190
  # @return [a customized Hash]
136
191
  # @since 2.0.5
137
192
  #
data/lib/oci8/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.0.2"
2
+ VERSION = "2.2.12"
3
3
  end
data/lib/oci8.rb CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  # --*- ruby -*--
3
2
  # This is based on yoshidam's oracle.rb.
4
3
  #
@@ -12,8 +11,11 @@ if RUBY_PLATFORM =~ /cygwin/
12
11
  # Cygwin manages environment variables by itself.
13
12
  # They don't synchroize with Win32's ones.
14
13
  # This set some Oracle's environment variables to win32's enviroment.
15
- require 'Win32API'
16
- win32setenv = Win32API.new('Kernel32.dll', 'SetEnvironmentVariableA', 'PP', 'I')
14
+ require 'fiddle'
15
+ win32setenv = Fiddle::Function.new( Fiddle.dlopen('Kernel32.dll')['SetEnvironmentVariableA'],
16
+ [Fiddle::TYPE_VOIDP,Fiddle::TYPE_VOIDP],
17
+ Fiddle::TYPE_INT )
18
+
17
19
  ['NLS_LANG', 'TNS_ADMIN', 'LOCAL'].each do |name|
18
20
  val = ENV[name]
19
21
  win32setenv.call(name, val && val.dup)
@@ -64,16 +66,56 @@ when 'rbx'
64
66
  so_basename += 'rbx'
65
67
  when 'jruby'
66
68
  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."
69
+ when 'truffleruby'
70
+ so_basename += 'truffleruby'
67
71
  else
68
72
  raise 'unsupported ruby engine: ' + RUBY_ENGINE
69
73
  end
70
74
 
75
+ dll_dir = nil
76
+ begin
77
+ require 'ruby_installer/runtime' # RubyInstaller2 for Windows
78
+
79
+ dll_arch = proc do |file|
80
+ begin
81
+ File.open(file, 'rb') do |f|
82
+ if f.read(2) == 'MZ' # IMAGE_DOS_HEADER.e_magic
83
+ f.seek(60, IO::SEEK_SET)
84
+ pe_offset = f.read(4).unpack('V')[0] # IMAGE_DOS_HEADER.e_lfanew
85
+ f.seek(pe_offset)
86
+ if f.read(4) == "PE\000\000" # IMAGE_NT_HEADERS.Signature
87
+ case f.read(2).unpack('v')[0] # IMAGE_FILE_HEADER.Machine
88
+ when 0x014c # IMAGE_FILE_MACHINE_I386
89
+ :x86
90
+ when 0x8664 # IMAGE_FILE_MACHINE_AMD64
91
+ :x64
92
+ end
93
+ end
94
+ end
95
+ end
96
+ rescue
97
+ nil
98
+ end
99
+ end
100
+
101
+ ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
102
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
103
+ if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
104
+ dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
105
+ break
106
+ end
107
+ end
108
+ rescue LoadError
109
+ end
110
+
71
111
  begin
72
112
  require so_basename
73
- rescue LoadError, OCIError
113
+ rescue LoadError
74
114
  require 'oci8/check_load_error'
75
115
  OCI8::Util::check_load_error($!)
76
116
  raise
117
+ ensure
118
+ dll_dir.remove if dll_dir
77
119
  end
78
120
 
79
121
  require 'oci8/version.rb'
@@ -103,6 +145,8 @@ class OCI8
103
145
  ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
104
146
  # @private
105
147
  ORAVER_12_1 = OCI8::OracleVersion.new(12, 1)
148
+ # @private
149
+ ORAVER_18 = OCI8::OracleVersion.new(18)
106
150
 
107
151
  # @private
108
152
  @@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
data/lib/ruby-oci8.rb ADDED
@@ -0,0 +1 @@
1
+ require 'oci8'
data/pre-distclean.rb CHANGED
@@ -1,6 +1,4 @@
1
- rm_f "#{curr_objdir}/lib/oci8.rb"
2
- rm_f "#{curr_objdir}/ext/oci8/oci8lib_18.map"
3
- rm_f "#{curr_objdir}/ext/oci8/oci8lib_191.map"
1
+ rm_f "#{curr_objdir}/ext/oci8/oci8lib_*.map"
4
2
  if RUBY_PLATFORM =~ /cygwin/
5
3
  rm_f "#{curr_objdir}/ext/oci8/OCI.def"
6
4
  rm_f "#{curr_objdir}/ext/oci8/libOCI.a"
data/ruby-oci8.gemspec CHANGED
@@ -34,10 +34,9 @@ spec = Gem::Specification.new do |s|
34
34
  s.description = <<EOS
35
35
  ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available with Oracle 10g or later including Oracle Instant Client.
36
36
  EOS
37
- s.has_rdoc = 'yard'
38
37
  s.authors = ['Kubo Takehiro']
39
38
  s.platform = gem_platform
40
- s.license = '2-clause BSD-style license'
39
+ s.license = 'BSD-2-Clause'
41
40
  files = File.read('dist-files').split("\n")
42
41
  if gem_platform == Gem::Platform::RUBY
43
42
  s.extensions << 'ext/oci8/extconf.rb'
@@ -51,7 +50,7 @@ EOS
51
50
  # add map files to analyze a core (minidump) file.
52
51
  so_vers.each do |ver|
53
52
  map_file = 'ext/oci8/oci8lib_#{ver}.map'
54
- so_files << map_file if File.exists? map_file
53
+ so_files << map_file if File.exist? map_file
55
54
  end
56
55
 
57
56
  # least version in so_vers
@@ -64,11 +63,7 @@ EOS
64
63
  raise "No compiled binary are found. Run make in advance."
65
64
  when 1
66
65
  puts "Binary gem for ruby #{so_vers.first}"
67
- if so_vers[0] < '2.0.0'
68
- s.required_ruby_version = "~> #{so_vermin}"
69
- else
70
- s.required_ruby_version = "~> #{so_vermin}.0"
71
- end
66
+ s.required_ruby_version = "~> #{so_vermin}"
72
67
  else
73
68
  puts "Binary gem for ruby #{so_vers.join(', ')}"
74
69
  s.required_ruby_version = ">= #{so_vermin}"
@@ -83,7 +78,7 @@ EOS
83
78
  end
84
79
  files << 'lib/oci8.rb'
85
80
  end
86
- s.require_paths = ['lib', 'ext/oci8']
81
+ s.require_paths = ['lib']
87
82
  s.files = files
88
83
  s.test_files = 'test/test_all.rb'
89
84
  s.extra_rdoc_files = ['README.md']
data/setup.rb CHANGED
@@ -189,7 +189,16 @@ class ConfigTable
189
189
  'the make program to compile ruby extentions' ] ],
190
190
  [ 'without-ext', [ 'no',
191
191
  'yes/no',
192
- 'does not compile/install ruby extentions' ] ]
192
+ 'does not compile/install ruby extentions' ] ],
193
+ [ 'with-instant-client-dir', ['',
194
+ 'path',
195
+ 'path to the Oracle instant client directory'] ],
196
+ [ 'with-instant-client-lib', ['',
197
+ 'path',
198
+ 'path to the Oracle instant client libraries'] ],
199
+ [ 'with-instant-client-include', ['',
200
+ 'path',
201
+ 'path to the Oracle instant client header files'] ]
193
202
  ]
194
203
  multipackage_descripters = [
195
204
  [ 'with', [ '',
@@ -277,7 +286,7 @@ class ConfigTable
277
286
 
278
287
  def initialize_from_table
279
288
  @table = {}
280
- DESCRIPTER.each do |k, (default, vname, desc, default2)|
289
+ DESCRIPTER.each do |k, (default, *)|
281
290
  @table[k] = default
282
291
  end
283
292
  end
data/test/README.md ADDED
@@ -0,0 +1,37 @@
1
+ Before running unit test:
2
+
3
+ 1. Connect to Oracle as sys
4
+ ```shell
5
+ $ sqlplus sys/<password_of_sys> as sysdba
6
+ SQL>
7
+ ```
8
+ 2. Create user ruby
9
+ ```sql
10
+ SQL> CREATE USER ruby IDENTIFIED BY oci8 DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
11
+ SQL> alter user ruby quota unlimited on users;
12
+ ```
13
+ 3. Grant the privilege to connect and execute.
14
+ ```sql
15
+ SQL> GRANT connect, resource, create view, create synonym TO ruby;
16
+ SQL> GRANT execute ON dbms_lock TO ruby;
17
+ ```
18
+ 4. Connect as ruby user.
19
+ ```shell
20
+ $ sqlplus ruby/oci8
21
+ SQL>
22
+ ```
23
+ 5. Create object types
24
+ ```sql
25
+ SQL> @test/setup_test_object.sql
26
+ SQL> @test/setup_test_package.sql
27
+ ```
28
+ 6. change $dbname in test/config.rb.
29
+
30
+ Then run the following command:
31
+ ```shell
32
+ $ make check
33
+ ```
34
+ or
35
+ ```
36
+ $ nmake check (If your compiler is MS Visual C++.)
37
+ ````
data/test/config.rb CHANGED
@@ -125,9 +125,16 @@ end
125
125
 
126
126
  class Minitest::Test
127
127
 
128
+ # @!visibility private
129
+ # dirty hack to suppress "warning: constant ::Fixnum is deprecated"
130
+ Fixnum = (0.class == ::Integer) ? ::Integer : ::Fixnum
131
+ # @!visibility private
132
+ # dirty hack to suppress "warning: constant ::Bignum is deprecated"
133
+ Bignum = (0.class == ::Integer) ? ::Integer : ::Bignum
134
+
128
135
  def get_oci8_connection()
129
136
  OCI8.new($dbuser, $dbpass, $dbname)
130
- rescue OCIError
137
+ rescue OCIError
131
138
  raise if $!.code != 12516 && $!.code != 12520
132
139
  # sleep a few second and try again if
133
140
  # the error code is ORA-12516 or ORA-12520.
@@ -10,6 +10,10 @@ drop type rb_test_obj_elem_array
10
10
  /
11
11
  drop type rb_test_obj_elem
12
12
  /
13
+ drop type rb_test_obj_sub
14
+ /
15
+ drop type rb_test_obj_base
16
+ /
13
17
  create type rb_test_obj_elem as object (
14
18
  x integer,
15
19
  y integer
@@ -57,6 +61,8 @@ create type rb_test_obj as object (
57
61
  obj_array_val rb_test_obj_elem_array,
58
62
  obj_ary_of_ary_val rb_test_obj_elem_ary_of_ary,
59
63
  date_val date,
64
+ timestamp_val timestamp(9),
65
+ timestamp_tz_val timestamp(9) with time zone,
60
66
  -- date_array_val rb_test_date_array,
61
67
 
62
68
  constructor function rb_test_obj(n number) return self as result,
@@ -68,19 +74,23 @@ create type rb_test_obj as object (
68
74
  member procedure member_proc(n in integer)
69
75
  )
70
76
  /
71
- create or replace type body rb_test_obj is
72
-
77
+ create type body rb_test_obj is
73
78
  constructor function rb_test_obj(n number) return self as result is
74
- function to_test_date(n number) return date is
75
- begin
76
- return to_date(to_char(1990 + n, 'FM0000') ||
77
- to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
78
- to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
79
- to_char(mod(round(n) * 9, 24), 'FM00') ||
80
- to_char(mod(round(n) * 11, 60), 'FM00') ||
81
- to_char(mod(round(n) * 13, 60), 'FM00'), 'yyyymmddhh24miss');
82
- end;
79
+ str varchar(28);
80
+ ts timestamp(9);
81
+ ts_tz timestamp(9) with time zone;
83
82
  begin
83
+ str := to_char(1990 + n, 'FM0000') ||
84
+ to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
85
+ to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
86
+ to_char(mod(round(n) * 9, 24), 'FM00') ||
87
+ to_char(mod(round(n) * 11, 60), 'FM00') ||
88
+ to_char(mod(round(n) * 13, 60), 'FM00') ||
89
+ to_char(mod(round(n) * 333333333, 1000000000), 'FM000000000');
90
+ ts := to_timestamp(str, 'yyyymmddhh24missff9');
91
+ str := str || to_char(mod(round(n) * 15, 24) - 11, 'FMS00') ||
92
+ to_char(mod(round(n) * 17, 60), 'FM00');
93
+ ts_tz := to_timestamp_tz(str, 'yyyymmddhh24missff9tzhtzm');
84
94
  self.int_val := n;
85
95
  self.flt_val := n;
86
96
  self.num_val := n;
@@ -92,7 +102,9 @@ create or replace type body rb_test_obj is
92
102
  self.nclob_val := to_clob(n);
93
103
  self.blob_val := to_blob(utl_raw.cast_to_raw(to_char(n)));
94
104
  self.obj_val := rb_test_obj_elem(n, n + 1);
95
- self.date_val := to_test_date(n);
105
+ self.date_val := ts;
106
+ self.timestamp_val := ts;
107
+ self.timestamp_tz_val := ts_tz;
96
108
  if self.int_val != 1 then
97
109
  self.int_array_val := rb_test_int_array(n, n + 1, n + 2);
98
110
  self.flt_array_val := rb_test_flt_array(n, n + 1, n + 2);
@@ -116,7 +128,7 @@ create or replace type body rb_test_obj is
116
128
 
117
129
  static function test_object_version return integer is
118
130
  begin
119
- return 2;
131
+ return 4;
120
132
  end;
121
133
 
122
134
  static function class_func(n number) return rb_test_obj is
@@ -167,5 +179,21 @@ begin
167
179
  end loop;
168
180
  end;
169
181
  /
170
- commit
182
+
183
+ create type rb_test_obj_base as object (
184
+ id varchar2(30)
185
+ ) not final
186
+ /
187
+ create type rb_test_obj_sub under rb_test_obj_base (
188
+ subid varchar2(30)
189
+ ) final
190
+ /
191
+ create or replace function rb_test_obj_get_object(get_base integer) return rb_test_obj_base is
192
+ begin
193
+ if get_base = 0 then
194
+ return rb_test_obj_base('base');
195
+ else
196
+ return rb_test_obj_sub('sub', 'subid');
197
+ end if;
198
+ end;
171
199
  /
@@ -0,0 +1,59 @@
1
+ create or replace package rb_test_pkg is
2
+ package_version pls_integer := 1;
3
+
4
+ type array_of_integer is array(50) of integer;
5
+ type table_of_pls_integer is table of pls_integer;
6
+ type table_of_boolean is table of boolean;
7
+ type indexed_table_of_varchar2 is table of varchar2(10) index by varchar2(5);
8
+ type rec1 is record (i pls_integer, j integer);
9
+ type rec2 is record (b boolean, it indexed_table_of_varchar2, rec rec1);
10
+ type table_of_rec1 is table of rec1;
11
+ type table_of_rec2 is table of rec2;
12
+
13
+ function sum_table_of_pls_integer(tbl in table_of_pls_integer) return pls_integer;
14
+ function add_rec1_values(tbl in table_of_rec1) return pls_integer;
15
+ procedure out_rec1_values(tbl out table_of_rec1);
16
+ end;
17
+ /
18
+ create or replace package body rb_test_pkg is
19
+ function sum_table_of_pls_integer(tbl in table_of_pls_integer) return pls_integer is
20
+ i pls_integer;
21
+ ret pls_integer := 0;
22
+ begin
23
+ for i in tbl.first..tbl.last loop
24
+ ret := ret + tbl(i);
25
+ end loop;
26
+ return ret;
27
+ end;
28
+
29
+ function add_rec1_values(tbl in table_of_rec1) return pls_integer is
30
+ i pls_integer;
31
+ ret pls_integer := 0;
32
+ begin
33
+ for i in tbl.first..tbl.last loop
34
+ ret := ret + nvl(tbl(i).i, 0) + nvl(tbl(i).j, 0);
35
+ end loop;
36
+ return ret;
37
+ end;
38
+
39
+ procedure out_rec1_values(tbl out table_of_rec1) is
40
+ i pls_integer;
41
+ rec1val rec1;
42
+ begin
43
+ tbl := table_of_rec1();
44
+ for i in 1..20 loop
45
+ tbl.extend;
46
+ if i mod 6 != 0 then
47
+ if i mod 3 != 0 then
48
+ rec1val.i := i;
49
+ rec1val.j := i;
50
+ else
51
+ rec1val.i := null;
52
+ rec1val.j := null;
53
+ end if;
54
+ tbl(i) := rec1val;
55
+ end if;
56
+ end loop;
57
+ end;
58
+ end;
59
+ /
data/test/test_all.rb CHANGED
@@ -5,9 +5,11 @@ require "#{srcdir}/config"
5
5
 
6
6
  require "#{srcdir}/test_oradate"
7
7
  require "#{srcdir}/test_oranumber"
8
+ require "#{srcdir}/test_bind_array.rb"
8
9
  require "#{srcdir}/test_bind_string"
9
10
  require "#{srcdir}/test_bind_time"
10
11
  require "#{srcdir}/test_bind_raw"
12
+ require "#{srcdir}/test_bind_integer"
11
13
  if $test_clob
12
14
  require "#{srcdir}/test_clob"
13
15
  end
@@ -24,6 +26,7 @@ require "#{srcdir}/test_oracle_version"
24
26
  require "#{srcdir}/test_error"
25
27
  require "#{srcdir}/test_connection_pool"
26
28
  require "#{srcdir}/test_object"
29
+ require "#{srcdir}/test_properties.rb"
27
30
 
28
31
  if OCI8.respond_to? :encoding
29
32
  require "#{srcdir}/test_encoding"
@@ -31,6 +34,7 @@ end
31
34
 
32
35
  if $oracle_version >= OCI8::ORAVER_12_1
33
36
  require "#{srcdir}/test_package_type"
37
+ require "#{srcdir}/test_bind_boolean.rb"
34
38
  end
35
39
 
36
40
  # Ruby/DBI
@@ -0,0 +1,70 @@
1
+ require 'oci8'
2
+ require File.dirname(__FILE__) + '/config'
3
+
4
+ class TestBindArray < Minitest::Test
5
+
6
+ def test_bind_array_names
7
+ assert_equal(":id_0", OCI8::in_cond(:id, []).names)
8
+ assert_equal(":id_0", OCI8::in_cond(:id, [1]).names)
9
+ assert_equal(":id_0, :id_1", OCI8::in_cond(:id, [1, 2]).names)
10
+ assert_equal(":id_0, :id_1, :id_2", OCI8::in_cond(:id, [1, 2, 3]).names)
11
+ end
12
+
13
+ def test_bind_array_values
14
+ assert_equal([[nil, String, nil]], OCI8::in_cond(:id, []).values)
15
+ assert_equal([[1, nil, nil]], OCI8::in_cond(:id, [1]).values)
16
+ assert_equal([[1, nil, nil], [2, nil, nil]], OCI8::in_cond(:id, [1, 2]).values)
17
+ assert_equal([[1, nil, nil], [2, nil, nil], [3, nil, nil]], OCI8::in_cond(:id, [1, 2, 3]).values)
18
+ end
19
+
20
+ def test_bind_array_values_containg_nil
21
+ assert_equal([[nil, String]], OCI8::in_cond(:id, [nil]).values)
22
+ assert_equal([[nil, Fixnum], [2, nil, nil], [3, nil, nil]], OCI8::in_cond(:id, [nil, 2, 3]).values)
23
+ assert_equal([[1, nil, nil], [nil, Fixnum], [3, nil, nil]], OCI8::in_cond(:id, [1, nil, 3]).values)
24
+ end
25
+
26
+ def test_bind_array_values_with_type
27
+ assert_equal([[nil, Integer, nil]], OCI8::in_cond(:id, [], Integer).values)
28
+ assert_equal([[1, Integer, nil]], OCI8::in_cond(:id, [1], Integer).values)
29
+ assert_equal([[1, Integer, nil], [2, Integer, nil]], OCI8::in_cond(:id, [1, 2], Integer).values)
30
+ assert_equal([[1, Integer, nil], [2, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [1, 2, 3], Integer).values)
31
+ assert_equal([[nil, Integer, nil], [2, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [nil, 2, 3], Integer).values)
32
+ assert_equal([[1, Integer, nil], [nil, Integer, nil], [3, Integer, nil]], OCI8::in_cond(:id, [1, nil, 3], Integer).values)
33
+ end
34
+
35
+ def test_select
36
+ @conn = get_oci8_connection
37
+ begin
38
+ drop_table('test_table')
39
+ @conn.exec(<<EOS)
40
+ CREATE TABLE test_table (ID NUMBER(38))
41
+ EOS
42
+ cursor = @conn.parse('insert into test_table values(:1)')
43
+ cursor.bind_param(1, nil, Integer)
44
+ [1, 3, 5].each do |id|
45
+ cursor.exec(id)
46
+ end
47
+ cursor.close
48
+
49
+ [
50
+ [],
51
+ [1],
52
+ [1, 2],
53
+ [1, 2, 3],
54
+ [nil],
55
+ [nil, 2, 3],
56
+ [1, nil, 3],
57
+ ].each do |ids|
58
+ in_cond = OCI8::in_cond(:id, ids)
59
+ cursor = @conn.exec("select * from test_table where id in (#{in_cond.names}) order by id", *in_cond.values)
60
+ ([1, 3, 5] & ids).each do |id|
61
+ assert_equal(id, cursor.fetch[0])
62
+ end
63
+ end
64
+
65
+ drop_table('test_table')
66
+ ensure
67
+ @conn.logoff
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,99 @@
1
+ # Low-level API
2
+ require 'oci8'
3
+ require File.dirname(__FILE__) + '/config'
4
+
5
+ class TestBindBoolean < Minitest::Test
6
+ def setup
7
+ @conn = get_oci8_connection()
8
+ end
9
+
10
+ def test_set_raw
11
+ stmt = <<EOS
12
+ DECLARE
13
+ bool_val boolean;
14
+ int_val pls_integer;
15
+ BEGIN
16
+ bool_val := :in;
17
+ IF bool_val THEN
18
+ int_val := 1;
19
+ ELSE
20
+ int_val := 0;
21
+ END IF;
22
+ :out := int_val;
23
+ END;
24
+ EOS
25
+ # explicit bind
26
+ cursor = @conn.parse(stmt)
27
+ cursor.bind_param(:in, nil, TrueClass)
28
+ cursor.bind_param(:out, nil, Integer)
29
+
30
+ cursor[:in] = true
31
+ cursor.exec
32
+ assert_equal(1, cursor[:out])
33
+
34
+ cursor[:in] = false
35
+ cursor.exec
36
+ assert_equal(0, cursor[:out])
37
+
38
+ # implicit bind
39
+ do_block_cnt = 0
40
+ @conn.exec(stmt, true, 0) do |in_val, out_val|
41
+ assert_equal(true, in_val)
42
+ assert_equal(1, out_val)
43
+ do_block_cnt += 1
44
+ end
45
+
46
+ @conn.exec(stmt, false, 0) do |in_val, out_val|
47
+ assert_equal(false, in_val)
48
+ assert_equal(0, out_val)
49
+ do_block_cnt += 1
50
+ end
51
+ assert_equal(2, do_block_cnt)
52
+ end
53
+
54
+ def test_get_raw
55
+ stmt = <<EOS
56
+ DECLARE
57
+ int_val pls_integer;
58
+ bool_val boolean;
59
+ BEGIN
60
+ int_val := :in;
61
+ IF int_val <> 0 THEN
62
+ bool_val := TRUE;
63
+ ELSE
64
+ bool_val := FALSE;
65
+ END IF;
66
+ :out := bool_val;
67
+ END;
68
+ EOS
69
+ cursor = @conn.parse(stmt)
70
+ cursor.bind_param(:in, nil, Integer)
71
+ cursor.bind_param(:out, nil, TrueClass)
72
+
73
+ cursor[:in] = 1
74
+ cursor.exec
75
+ assert_equal(true, cursor[:out])
76
+
77
+ cursor[:in] = 0
78
+ cursor.exec
79
+ assert_equal(false, cursor[:out])
80
+
81
+ do_block_cnt = 0
82
+ @conn.exec(stmt, 1, true) do |in_val, out_val|
83
+ assert_equal(1, in_val)
84
+ assert_equal(true, out_val)
85
+ do_block_cnt += 1
86
+ end
87
+
88
+ @conn.exec(stmt, 0, true) do |in_val, out_val|
89
+ assert_equal(0, in_val)
90
+ assert_equal(false, out_val)
91
+ do_block_cnt += 1
92
+ end
93
+ assert_equal(2, do_block_cnt)
94
+ end
95
+
96
+ def teardown
97
+ @conn.logoff
98
+ end
99
+ end