ruby-oci8 2.2.5.1-x64-mingw32 → 2.2.9-x64-mingw32

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.
@@ -34,7 +34,6 @@ 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
39
  s.license = 'BSD-2-Clause'
@@ -79,7 +78,7 @@ EOS
79
78
  end
80
79
  files << 'lib/oci8.rb'
81
80
  end
82
- s.require_paths = ['lib', 'ext/oci8']
81
+ s.require_paths = ['lib']
83
82
  s.files = files
84
83
  s.test_files = 'test/test_all.rb'
85
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
@@ -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
+ ````
@@ -134,7 +134,7 @@ class Minitest::Test
134
134
 
135
135
  def get_oci8_connection()
136
136
  OCI8.new($dbuser, $dbpass, $dbname)
137
- rescue OCIError
137
+ rescue OCIError
138
138
  raise if $!.code != 12516 && $!.code != 12520
139
139
  # sleep a few second and try again if
140
140
  # the error code is ORA-12516 or ORA-12520.
@@ -61,6 +61,8 @@ create type rb_test_obj as object (
61
61
  obj_array_val rb_test_obj_elem_array,
62
62
  obj_ary_of_ary_val rb_test_obj_elem_ary_of_ary,
63
63
  date_val date,
64
+ timestamp_val timestamp(9),
65
+ timestamp_tz_val timestamp(9) with time zone,
64
66
  -- date_array_val rb_test_date_array,
65
67
 
66
68
  constructor function rb_test_obj(n number) return self as result,
@@ -72,19 +74,23 @@ create type rb_test_obj as object (
72
74
  member procedure member_proc(n in integer)
73
75
  )
74
76
  /
75
- create or replace type body rb_test_obj is
76
-
77
+ create type body rb_test_obj is
77
78
  constructor function rb_test_obj(n number) return self as result is
78
- function to_test_date(n number) return date is
79
- begin
80
- return to_date(to_char(1990 + n, 'FM0000') ||
81
- to_char(mod(round(n) * 5, 12) + 1, 'FM00') ||
82
- to_char(mod(round(n) * 7, 27) + 1, 'FM00') ||
83
- to_char(mod(round(n) * 9, 24), 'FM00') ||
84
- to_char(mod(round(n) * 11, 60), 'FM00') ||
85
- to_char(mod(round(n) * 13, 60), 'FM00'), 'yyyymmddhh24miss');
86
- end;
79
+ str varchar(28);
80
+ ts timestamp(9);
81
+ ts_tz timestamp(9) with time zone;
87
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');
88
94
  self.int_val := n;
89
95
  self.flt_val := n;
90
96
  self.num_val := n;
@@ -96,7 +102,9 @@ create or replace type body rb_test_obj is
96
102
  self.nclob_val := to_clob(n);
97
103
  self.blob_val := to_blob(utl_raw.cast_to_raw(to_char(n)));
98
104
  self.obj_val := rb_test_obj_elem(n, n + 1);
99
- self.date_val := to_test_date(n);
105
+ self.date_val := ts;
106
+ self.timestamp_val := ts;
107
+ self.timestamp_tz_val := ts_tz;
100
108
  if self.int_val != 1 then
101
109
  self.int_array_val := rb_test_int_array(n, n + 1, n + 2);
102
110
  self.flt_array_val := rb_test_flt_array(n, n + 1, n + 2);
@@ -120,7 +128,7 @@ create or replace type body rb_test_obj is
120
128
 
121
129
  static function test_object_version return integer is
122
130
  begin
123
- return 3;
131
+ return 4;
124
132
  end;
125
133
 
126
134
  static function class_func(n number) return rb_test_obj is
@@ -26,6 +26,7 @@ require "#{srcdir}/test_oracle_version"
26
26
  require "#{srcdir}/test_error"
27
27
  require "#{srcdir}/test_connection_pool"
28
28
  require "#{srcdir}/test_object"
29
+ require "#{srcdir}/test_properties.rb"
29
30
 
30
31
  if OCI8.respond_to? :encoding
31
32
  require "#{srcdir}/test_encoding"
@@ -22,9 +22,8 @@ class TestBreak < Minitest::Test
22
22
  @@server_is_runing_on_windows = nil
23
23
  def server_is_runing_on_windows?
24
24
  if @@server_is_runing_on_windows.nil?
25
- @@server_is_runing_on_windows = false
26
- @conn.exec('select banner from v$version') do |row|
27
- @@server_is_runing_on_windows = true if row[0].include? 'Windows'
25
+ @conn.exec('select dbms_utility.port_string from dual') do |row|
26
+ @@server_is_runing_on_windows = row[0].include? '/WIN'
28
27
  end
29
28
  end
30
29
  @@server_is_runing_on_windows
@@ -63,7 +62,7 @@ class TestBreak < Minitest::Test
63
62
  expect = []
64
63
  expect[PLSQL_DONE] = TIME_IN_PLSQL
65
64
  expect[OCIBREAK] = "Invalid status"
66
- if defined? Rubinius and Rubinius::VERSION >= "2.0"
65
+ if (defined? Rubinius and Rubinius::VERSION >= "2.0") || (defined? RUBY_ENGINE and RUBY_ENGINE == "truffleruby")
67
66
  # Rubinius 2.0.0.
68
67
  # DBMS_LOCK.SLEEP blocks ruby threads which try to call C-API.
69
68
  expect[SEND_BREAK] = TIME_TO_BREAK
@@ -24,22 +24,6 @@ class TestCLob < Minitest::Test
24
24
  lob.close
25
25
  end
26
26
 
27
- def test_insert_with_flush
28
- filename = File.basename($lobfile)
29
- @conn.exec("DELETE FROM test_table WHERE filename = :1", filename)
30
- @conn.exec("INSERT INTO test_table(filename, content) VALUES (:1, EMPTY_CLOB())", filename)
31
- cursor = @conn.exec("SELECT content FROM test_table WHERE filename = :1 FOR UPDATE", filename)
32
- lob = cursor.fetch[0]
33
- lob.sync = false
34
- open($lobfile) do |f|
35
- while s = f.read(1000)
36
- lob.write(s)
37
- end
38
- end
39
- lob.flush
40
- lob.close
41
- end
42
-
43
27
  def test_insert_symbol
44
28
  filename = 'test_symbol'
45
29
  value = :foo_bar
@@ -76,6 +60,9 @@ class TestCLob < Minitest::Test
76
60
 
77
61
  # https://github.com/kubo/ruby-oci8/issues/20
78
62
  def test_github_issue_20
63
+ # Skip this test if FULLTEST isn't set because it takes 4 minutes in my Linux box.
64
+ return if ENV['FULLTEST']
65
+
79
66
  lob1 = OCI8::CLOB.new(@conn, ' ' * (1024 * 1024))
80
67
  lob1.read(1) # to suppress `warning: assigned but unused variable - lob1`
81
68
  begin
@@ -1,6 +1,5 @@
1
1
  require 'oci8'
2
2
  require File.dirname(__FILE__) + '/config'
3
- require 'scanf'
4
3
 
5
4
  class TestDateTime < Minitest::Test
6
5
 
@@ -28,6 +27,12 @@ class TestDateTime < Minitest::Test
28
27
  convert_to_datetime($1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, subsec, $8)
29
28
  end
30
29
 
30
+ # 'YYYY-MM-DD HH24:MI:SS' or 'YYYY-MM-DD HH24:MI:SS.FF6' to array
31
+ def string_to_array(str)
32
+ /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+)(?:\.(\d+))?/ =~ str
33
+ [$1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i, $7 ? $7.to_i / 1000 : 0]
34
+ end
35
+
31
36
  def setup
32
37
  @conn = get_oci8_connection
33
38
  end
@@ -43,7 +48,7 @@ class TestDateTime < Minitest::Test
43
48
  @conn.exec(<<-EOS) do |row|
44
49
  SELECT TO_DATE('#{date}', 'YYYY-MM-DD HH24:MI:SS') FROM dual
45
50
  EOS
46
- assert_equal(Time.local(*date.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
51
+ assert_equal(Time.local(*string_to_array(date)), row[0])
47
52
  end
48
53
  end
49
54
  end
@@ -94,7 +99,7 @@ EOS
94
99
  @conn.exec(<<-EOS) do |row|
95
100
  SELECT TO_TIMESTAMP('#{date}', 'YYYY-MM-DD HH24:MI:SS.FF') FROM dual
96
101
  EOS
97
- assert_equal(Time.local(*date.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
102
+ assert_equal(Time.local(*string_to_array(date)), row[0])
98
103
  end
99
104
  end
100
105
  end
@@ -1,6 +1,12 @@
1
1
  require 'oci8'
2
2
  require File.dirname(__FILE__) + '/config'
3
3
 
4
+ class Time
5
+ def inspect
6
+ self.strftime("%Y-%m-%d %H:%M:%S.%N %:z")
7
+ end
8
+ end
9
+
4
10
  conn = OCI8.new($dbuser, $dbpass, $dbname)
5
11
  error_message = nil
6
12
  begin
@@ -22,7 +28,7 @@ begin
22
28
 
23
29
  begin
24
30
  version = RbTestObj.test_object_version(conn)
25
- error_message = "Invalid test object version" if version != 3
31
+ error_message = "Invalid test object version" if version != 4
26
32
  rescue NoMethodError
27
33
  raise unless $!.to_s.include?('test_object_version')
28
34
  error_message = "rb_test_obj.test_object_version is not declared."
@@ -100,7 +106,8 @@ class TestObj1 < Minitest::Test
100
106
  attr_reader :obj_array_val
101
107
  attr_reader :obj_ary_of_ary_val
102
108
  attr_reader :date_val
103
- # attr_reader :date_array_val
109
+ attr_reader :timestamp_val
110
+ attr_reader :timestamp_tz_val
104
111
 
105
112
  attr_accessor :assertions
106
113
 
@@ -109,16 +116,28 @@ class TestObj1 < Minitest::Test
109
116
  @assertions = 0
110
117
  end
111
118
 
112
- def to_test_date(n)
119
+ def to_test_datetime(n, type)
113
120
  year = (1990 + n).round
114
121
  month = (n.round * 5) % 12 + 1
115
122
  mday = (n.round * 7) % 27 + 1
116
123
  hour = (n.round * 9) % 24
117
124
  minute = (n.round * 11) % 60
118
125
  sec = (n.round * 13) % 60
119
- convert_to_time(year, month, mday, hour, minute, sec, 0, nil)
126
+ nsec = if type == :date
127
+ 0
128
+ else
129
+ ((n.round * 333_333_333) % 1_000_000_000).to_r / 1_000_000_000
130
+ end
131
+ tz = if type == :timestamp_tz
132
+ tzh = (n.round * 15) % 24 - 11
133
+ tzm = (n.round * 17) % 60
134
+ format('%+03d:%02d', tzh, tzm)
135
+ else
136
+ nil
137
+ end
138
+ convert_to_time(year, month, mday, hour, minute, sec, nsec, tz)
120
139
  end
121
- private :to_test_date
140
+ private :to_test_datetime
122
141
 
123
142
  def next
124
143
  @n += 1.2
@@ -135,7 +154,9 @@ class TestObj1 < Minitest::Test
135
154
  @nclob_val = @str_val
136
155
  @blob_val = @str_val
137
156
  @obj_val = ExpectedValObjElem.new(@int_val, @int_val + 1)
138
- @date_val = to_test_date(@n)
157
+ @date_val = to_test_datetime(@n, :date)
158
+ @timestamp_val = to_test_datetime(@n, :timestamp)
159
+ @timestamp_tz_val = to_test_datetime(@n, :timestamp_tz)
139
160
  if @int_val == 1
140
161
  @int_array_val = nil
141
162
  @flt_array_val = nil
@@ -199,7 +220,8 @@ class TestObj1 < Minitest::Test
199
220
  obj_array_val = val[18]
200
221
  obj_ary_of_ary_val = val[19]
201
222
  date_val = val[20]
202
- # date_array_val = val[18]
223
+ timestamp_val = val[21]
224
+ timestamp_tz_val = val[22]
203
225
  else
204
226
  assert_instance_of(RbTestObj, val)
205
227
  int_val = val.int_val
@@ -223,7 +245,8 @@ class TestObj1 < Minitest::Test
223
245
  obj_array_val = val.obj_array_val
224
246
  obj_ary_of_ary_val = val.obj_ary_of_ary_val
225
247
  date_val = val.date_val
226
- # date_array_val = val.date_array_val
248
+ timestamp_val = val.timestamp_val
249
+ timestamp_tz_val = val.timestamp_tz_val
227
250
  end
228
251
 
229
252
  assert_equal(@int_val, int_val)
@@ -267,7 +290,8 @@ class TestObj1 < Minitest::Test
267
290
  assert_nil(obj_ary_of_ary_val)
268
291
  end
269
292
  assert_equal(@date_val, date_val)
270
- # assert_equal(@date_array_val, date_array_val && date_array_val.to_ary)
293
+ assert_equal(@timestamp_val, timestamp_val)
294
+ assert_equal(@timestamp_tz_val, timestamp_tz_val)
271
295
  end
272
296
 
273
297
  def assert_array_in_delta(exp, val)
@@ -25,53 +25,142 @@ EOS
25
25
  drop_table('test_rename_table')
26
26
  end
27
27
 
28
- # USE_DYNAMIC_FETCH doesn't work well...
29
- # This test is disabled.
30
- def _test_long_type
31
- drop_table('test_table')
32
- @conn.exec('CREATE TABLE test_table (id number(38), lng long)')
33
- test_data1 = 'a' * 70000
34
- test_data2 = 'b' * 3000
35
- test_data3 = nil
36
- test_data4 = 'c' * 70000
37
- @conn.exec('insert into test_table values (:1, :2)', 1, test_data1)
38
- @conn.exec('insert into test_table values (:1, :2)', 2, [test_data2, :long])
39
- @conn.exec('insert into test_table values (:1, :2)', 3, [nil, :long])
40
- @conn.exec('insert into test_table values (:1, :2)', 4, [test_data4, :long])
41
-
42
- [8000, 65535, 65536, 80000].each do |read_len|
43
- @conn.long_read_len = read_len
44
- cursor = @conn.parse('SELECT lng from test_table order by id')
45
- cursor.exec
46
- assert_equal(test_data1, cursor.fetch[0])
47
- assert_equal(test_data2, cursor.fetch[0])
48
- assert_equal(test_data3, cursor.fetch[0])
49
- assert_equal(test_data4, cursor.fetch[0])
50
- cursor.close
28
+ # Set `OCI8::BindType::Base.initial_chunk_size = 5` to
29
+ # use the following test data.
30
+ LONG_TEST_DATA = [
31
+ # initial chunk size: 5 (total buffer size: 5)
32
+ 'a' * 4, 'b' * 5, 'c' * 6, 'd' * 5, 'e' * 4,
33
+ # second chunk size: 10 (total buffer size: 15)
34
+ 'f' * 14, 'g' * 15, 'h' * 16, 'i' * 15, 'j' * 14,
35
+ # third chunk size: 20 (total buffer size: 35)
36
+ 'k' * 34, 'l' * 35, 'm' * 36, 'n' * 35, 'o' * 34,
37
+ # use data around initial chunk size again
38
+ 'p' * 4, 'q' * 5, 'r' * 6, 's' * 5, 't' * 4,
39
+ # special data
40
+ '', nil,
41
+ ]
42
+
43
+ def test_long_type
44
+ clob_bind_type = OCI8::BindType::Mapping[:clob]
45
+ blob_bind_type = OCI8::BindType::Mapping[:blob]
46
+ initial_cunk_size = OCI8::BindType::Base.initial_chunk_size
47
+ begin
48
+ OCI8::BindType::Base.initial_chunk_size = 5
49
+ @conn.prefetch_rows = LONG_TEST_DATA.size / 3
50
+ drop_table('test_table')
51
+ ascii_enc = Encoding.find('US-ASCII')
52
+ 0.upto(1) do |i|
53
+ if i == 0
54
+ @conn.exec("CREATE TABLE test_table (id number(38), long_column long, clob_column clob)")
55
+ cursor = @conn.parse('insert into test_table values (:1, :2, :3)')
56
+ cursor.bind_param(1, nil, Integer)
57
+ cursor.bind_param(2, nil, :long)
58
+ cursor.bind_param(3, nil, :clob)
59
+ lob = OCI8::CLOB.new(@conn, '')
60
+ enc = Encoding.default_internal || OCI8.encoding
61
+ else
62
+ @conn.exec("CREATE TABLE test_table (id number(38), long_raw_column long raw, blob_column blob)")
63
+ cursor = @conn.parse('insert into test_table values (:1, :2, :3)')
64
+ cursor.bind_param(1, nil, Integer)
65
+ cursor.bind_param(2, nil, :long_raw)
66
+ cursor.bind_param(3, nil, :blob)
67
+ lob = OCI8::BLOB.new(@conn, '')
68
+ enc = Encoding.find('ASCII-8BIT')
69
+ end
70
+
71
+ LONG_TEST_DATA.each_with_index do |data, index|
72
+ cursor[1] = index
73
+ cursor[2] = data
74
+ if data.nil?
75
+ cursor[3] = nil
76
+ else
77
+ lob.rewind
78
+ lob.write(data)
79
+ lob.size = data.size
80
+ cursor[3] = lob
81
+ end
82
+ cursor.exec
83
+ end
84
+ cursor.close
85
+
86
+ cursor = @conn.parse('SELECT * from test_table order by id')
87
+ cursor.exec
88
+ LONG_TEST_DATA.each_with_index do |data, index|
89
+ row = cursor.fetch
90
+ assert_equal(index, row[0])
91
+ if data.nil?
92
+ assert_nil(row[1])
93
+ assert_nil(row[2])
94
+ elsif data.empty?
95
+ # '' is inserted to the long or long raw column as null.
96
+ assert_nil(row[1])
97
+ # '' is inserted to the clob or blob column as an empty clob.
98
+ # It is fetched as '' when the data is read using a LOB locator.
99
+ assert_equal(data, clob_data = row[2].read)
100
+ assert_equal(ascii_enc, clob_data.encoding)
101
+ else
102
+ assert_equal(data, row[1])
103
+ assert_equal(data, clob_data = row[2].read)
104
+ assert_equal(enc, row[1].encoding)
105
+ assert_equal(enc, clob_data.encoding)
106
+ end
107
+ end
108
+ assert_nil(cursor.fetch)
109
+ cursor.close
110
+
111
+ begin
112
+ OCI8::BindType::Mapping[:clob] = OCI8::BindType::Long
113
+ OCI8::BindType::Mapping[:blob] = OCI8::BindType::LongRaw
114
+ cursor = @conn.parse('SELECT * from test_table order by id')
115
+ cursor.exec
116
+ LONG_TEST_DATA.each_with_index do |data, index|
117
+ row = cursor.fetch
118
+ assert_equal(index, row[0])
119
+ if data.nil?
120
+ assert_nil(row[1])
121
+ assert_nil(row[2])
122
+ elsif data.empty?
123
+ # '' is inserted to the long or long raw column as null.
124
+ assert_nil(row[1])
125
+ # '' is inserted to the clob or blob column as an empty clob.
126
+ # However it is fetched as nil.
127
+ assert_nil(row[2])
128
+ else
129
+ assert_equal(data, row[1])
130
+ assert_equal(data, row[2])
131
+ assert_equal(enc, row[1].encoding)
132
+ assert_equal(enc, row[2].encoding)
133
+ end
134
+ end
135
+ assert_nil(cursor.fetch)
136
+ cursor.close
137
+ ensure
138
+ OCI8::BindType::Mapping[:clob] = clob_bind_type
139
+ OCI8::BindType::Mapping[:blob] = blob_bind_type
140
+ end
141
+ drop_table('test_table')
142
+ end
143
+ ensure
144
+ OCI8::BindType::Base.initial_chunk_size = initial_cunk_size
51
145
  end
52
146
  drop_table('test_table')
53
147
  end
54
148
 
55
- def test_long_type
56
- @conn.long_read_len = 80000
57
- drop_table('test_table')
58
- @conn.exec('CREATE TABLE test_table (id number(38), lng long)')
59
- test_data1 = 'a' * 70000
60
- test_data2 = 'b' * 3000
61
- test_data4 = 'c' * 70000
62
- @conn.exec('insert into test_table values (:1, :2)', 1, test_data1)
63
- @conn.exec('insert into test_table values (:1, :2)', 2, [test_data2, :long])
64
- @conn.exec('insert into test_table values (:1, :2)', 3, [nil, :long])
65
- @conn.exec('insert into test_table values (:1, :2)', 4, [test_data4, :long])
66
-
67
- cursor = @conn.parse('SELECT lng from test_table order by id')
68
- cursor.exec
69
- assert_equal(test_data1, cursor.fetch[0])
70
- assert_equal(test_data2, cursor.fetch[0])
71
- assert_nil(cursor.fetch[0])
72
- assert_equal(test_data4, cursor.fetch[0])
73
- cursor.close
74
- drop_table('test_table')
149
+ def test_bind_long_data
150
+ initial_cunk_size = OCI8::BindType::Base.initial_chunk_size
151
+ begin
152
+ OCI8::BindType::Base.initial_chunk_size = 5
153
+ cursor = @conn.parse("begin :1 := '<' || :2 || '>'; end;")
154
+ cursor.bind_param(1, nil, :long)
155
+ cursor.bind_param(2, nil, :long)
156
+ (LONG_TEST_DATA + ['z' * 4000]).each do |data|
157
+ cursor[2] = data
158
+ cursor.exec
159
+ assert_equal("<#{data}>", cursor[1])
160
+ end
161
+ ensure
162
+ OCI8::BindType::Base.initial_chunk_size = initial_cunk_size
163
+ end
75
164
  end
76
165
 
77
166
  def test_select
@@ -450,6 +539,7 @@ EOS
450
539
  assert_nil(@conn.last_error)
451
540
  @conn.last_error = 'dummy'
452
541
  cursor = @conn.parse('select col1, max(col2) from (select 1 as col1, null as col2 from dual) group by col1')
542
+ cursor.prefetch_rows = 1
453
543
  assert_nil(@conn.last_error)
454
544
 
455
545
  # When an OCI function returns OCI_SUCCESS_WITH_INFO, OCI8#last_error is set.
@@ -491,9 +581,44 @@ EOS
491
581
  else
492
582
  raise "Unknown column size #{column_size}"
493
583
  end
494
- driver_name = cursor.fetch[0]
584
+ driver_name = cursor.fetch[0].strip
495
585
  cursor.close
496
586
  assert_equal(expected_value, driver_name)
497
587
  end
498
588
  end
589
+
590
+ def test_server_version
591
+ cursor = @conn.exec("select * from product_component_version where product like 'Oracle Database %'")
592
+ row = cursor.fetch_hash
593
+ cursor.close
594
+ ver = if OCI8::oracle_client_version >= OCI8::ORAVER_18
595
+ row['VERSION_FULL'] || row['VERSION']
596
+ else
597
+ # OCI8#oracle_server_version could not get infomation corresponding
598
+ # to VERSION_FULL when the Oracle client version is below 18.1.
599
+ row['VERSION']
600
+ end
601
+ assert_equal(ver, @conn.oracle_server_version.to_s)
602
+ end
603
+
604
+ def test_array_fetch
605
+ drop_table('test_table')
606
+ @conn.exec("CREATE TABLE test_table (id number, val clob)")
607
+ cursor = @conn.parse("INSERT INTO test_table VALUES (:1, :2)")
608
+ 1.upto(10) do |i|
609
+ cursor.exec(i, ('a'.ord + i).chr * i)
610
+ end
611
+ cursor.close
612
+ cursor = @conn.parse("select * from test_table where id <= :1 order by id")
613
+ cursor.prefetch_rows = 4
614
+ [1, 6, 2, 7, 3, 8, 4, 9, 5, 10].each do |i|
615
+ cursor.exec(i)
616
+ 1.upto(i) do |j|
617
+ row = cursor.fetch
618
+ assert_equal(j, row[0])
619
+ assert_equal(('a'.ord + j).chr * j, row[1].read)
620
+ end
621
+ assert_nil(cursor.fetch)
622
+ end
623
+ end
499
624
  end # TestOCI8