ruby-oci8 2.2.6.1-x64-mingw32 → 2.2.7-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7daaaef36f86bf96ea23fadb32362581678f244f
4
- data.tar.gz: 8cb4e9c01d683a12de6cb7bf7796382f4fde824a
3
+ metadata.gz: 1ae1a2b34598cbb82865cfe971db9059f8bc8825
4
+ data.tar.gz: d22f83c3bdf7c46b18caeaea28d9cd1f13dd21f7
5
5
  SHA512:
6
- metadata.gz: d47dadf8e61c1ba8311cf3ec7fb5e9b00926e4d68b64d4bddcc84544e59fdb5f5ded665fbc52da61c6ab72c207babab65b7beac57ce48e80900c59e692dac3f4
7
- data.tar.gz: 7ec1b47a1c87c445a6b178db64298aa99b70bf504f1ef34ea27f850f1b0e7c8e550ce3ae78ce38434c2e98abfc71335610c6567c50bfa3d22b4df50b33f7769f
6
+ metadata.gz: 3bf46089dafc3a9466283d52bcfb5e5249c65fce1d4b072018d2a853beb0b637917eb6d17cb1efb520d40e551f59c32c862e0b5961645561750b3bfe07c7c1b2
7
+ data.tar.gz: 8ce43483d58f631c50a6f888cff81888218830b0001510eb8c44f060fcdb416622d35e9ad21acbbed314964153a9aaf084ee7338c97efbf2f9af826d3917ab14
data/ChangeLog CHANGED
@@ -1,11 +1,60 @@
1
- 2018-09-16 Kubo Takehiro <kubo@jiubao.org>
2
- * NEWS: Add changes between 2.2.6 and 2.2.6.1
3
- * lib/oci8/version.rb: Update to 2.2.6.1
1
+ 2019-01-06 Kubo Takehiro <kubo@jiubao.org>
2
+ * NEWS: Add changes between 2.2.6.1 and 2.2.7.
3
+ * lib/oci8/version.rb: Update to 2.2.7
4
+
5
+ 2019-01-06 Kubo Takehiro <kubo@jiubao.org>
6
+ * mkpkg-win32.rb, ruby-oci8.gemspec: Build binary gems for ruby 2.6
7
+ on Windows.
8
+
9
+ 2019-01-06 Kubo Takehiro <kubo@jiubao.org>
10
+ * ext/oci8/oci8.c: Updata doc comments for OCI8#long_read_len
11
+ and OCI8#long_read_len=. These are deprecated.
12
+
13
+ 2019-01-03 Kubo Takehiro <kubo@jiubao.org>
14
+ * lib/oci8/check_load_error.rb: Use fiddle instead of Win32API
15
+ to call WIN32 functions.
16
+
17
+ 2019-01-03 Kubo Takehiro <kubo@jiubao.org>
18
+ * lib/oci8/check_load_error.rb: Add more error diagnostics
19
+ when 'require "oci8"' fails with "OCI.DLL: 126(The specified
20
+ module could not be found.)".
21
+
22
+ 2019-01-03 Kubo Takehiro <kubo@jiubao.org>
23
+ * lib/oci8.rb, lib/oci8/check_load_error.rb: Exclude empty
24
+ parts of PATH on Windows.
25
+
26
+ 2018-12-23 Kubo Takehiro <kubo@jiubao.org>
27
+ * lib/oci8/check_load_error.rb: Check OCI.DLL archtecture
28
+ when load error. It worked for ruby installer but not
29
+ for ruby installer2.
30
+
31
+ 2018-12-23 Kubo Takehiro <kubo@jiubao.org>
32
+ * docs/install-instant-client.md: Add information about
33
+ the MSVC redistributable package required by Oracle 18.3 client.
4
34
 
5
35
  2018-09-16 Kubo Takehiro <kubo@jiubao.org>
6
36
  * ext/oci8/hook_funcs.c: Fix "No shared library is found to hook." on macOS.
7
37
  (oracle-enhanced issue #1768)
8
38
 
39
+ 2018-09-11 Kubo Takehiro <kubo@jiubao.org>
40
+ * ext/oci8/object.c, lib/oci8/cursor.rb: Change the internal structure
41
+ about object type binding to use array fetching for object types.
42
+
43
+ 2018-09-09 Kubo Takehiro <kubo@jiubao.org>
44
+ * ext/oci8/lob.c: Read lob data without checking readable size to
45
+ reduce number of network round trips from two to one.
46
+
47
+ 2018-09-05 Kubo Takehiro <kubo@jiubao.org>
48
+ * ext/oci8/bind.c, ext/oci8/stmt.c, lib/oci8/cursor.rb,
49
+ lib/oci8/oci8.rb, test/test_oci8.rb: Use array fetching when
50
+ LOB colums are in a query and no object types are in the query.
51
+
52
+ 2018-09-02 Kubo Takehiro <kubo@jiubao.org>
53
+ * ext/oci8/apiwrap.yml, ext/oci8/bind.c, ext/oci8/stmt.c,
54
+ lib/oci8/bindtype.rb, test/test_oci8.rb: Rewrite OCI8::BindType::Long
55
+ and OCI8::BindType::LongRaw to handle up to 2 gigabyte data using
56
+ dynamically allocated buffers.
57
+
9
58
  2018-08-22 Kubo Takehiro <kubo@jiubao.org>
10
59
  * NEWS: Add changes between 2.2.5.1 and 2.2.6
11
60
  * lib/oci8/version.rb: Update to 2.2.6
data/NEWS CHANGED
@@ -1,15 +1,67 @@
1
1
  # @markup markdown
2
2
 
3
- 2.2.6.1
4
- =======
3
+ 2.2.7 (2019-01-06)
4
+ ==================
5
+
6
+ Incompatible Changes
7
+ --------------------
8
+
9
+ ### `OCI8#long_read_len` and `OCI8#long_read_len=` do nothing.
10
+
11
+ When `LONG`, `LONG RAW` or `XMLTYPE` data were fetched, the data were
12
+ truncated at `OCI8#long_read_len`. The maximum size of data had
13
+ been 4 gigabytes since this release.
14
+
15
+ `OCI8#long_read_len` and `OCI8#long_read_len=` remain for code-compatibility
16
+ but do nothing.
17
+
18
+ Improvement
19
+ -----------
20
+
21
+ ### The number of network round trips was reduced when LOB data are read.
22
+
23
+ When LOB data are read, ruby-oci8 before 2.2.7 does the followings:
24
+
25
+ 1. Gets the size of the LOB.
26
+ 2. Allocate buffer to hold the data.
27
+ 3. Read the LOB contents.
28
+
29
+ This requires two round trips.
30
+
31
+ It now does the followings:
32
+
33
+ 1. Request the server to get LOB contents up to 4 gigabytes.
34
+ 2. Read the LOB contents and allocate buffer when the size is insufficient.
35
+ 3. If the total length of received data is less than 4 gigabytes, all data
36
+ are read. If not, go to the first step to read next 4 gigabytes.
37
+
38
+ This requires only one round trip if the size is less than 4 gigabytes.
39
+
40
+ ### Use array fetching instead of prefetching when LOB columns are in queries
41
+
42
+ When LOB columns are in queries, prefetching doesn't seem to work. Rows
43
+ are fetched one by one according to data captured by network packet sniffer.
44
+ So array fetching is used instead of prefetching to reduce the number of
45
+ network round trips.
46
+
47
+ ### Add error diagnostics when `'require "oci8"'` fails on Windows.
48
+
49
+ When `'require "oci8"'` fails with "OCI.DLL: 126(The specified module could not be found.)"
50
+ on Windows, the cause is not always that OCI.DLL is not found. It may
51
+ be incorrect architecture, missing dependent DLLs and so on.
52
+ Ruby-oci8 checks PATH and DLL files when the error is raised and change
53
+ the error message to reasonable one as possible.
54
+
55
+ 2.2.6.1 (2018-09-16)
56
+ ====================
5
57
 
6
58
  Fixed issue
7
59
  -----------
8
60
  Fix "No shared library is found to hook." on macOS.
9
61
  (rsim/oracle-enhanced#1768)
10
62
 
11
- 2.2.6
12
- =====
63
+ 2.2.6 (2018-08-22)
64
+ ==================
13
65
 
14
66
  This release fixed issues about Oracle 18c except one.
15
67
 
@@ -47,8 +99,8 @@ communication channel."
47
99
 
48
100
  (github issue #185)
49
101
 
50
- 2.2.5.1
51
- =======
102
+ 2.2.5.1 (2017-12-27)
103
+ ====================
52
104
 
53
105
  No updates except tests. The version number was changed just to release
54
106
  binary gems for ruby 2.5 on Windows.
@@ -57,8 +109,8 @@ binary gems for ruby 2.5 on Windows.
57
109
 
58
110
  (github issue #180, #181)
59
111
 
60
- 2.2.5
61
- =====
112
+ 2.2.5 (2017-10-21)
113
+ ==================
62
114
 
63
115
  New Features
64
116
  ------------
@@ -115,8 +167,8 @@ Other Changes
115
167
  See {file:docs/number-type-mapping.md Number Type Mapping between Oracle and Ruby}.
116
168
  (github issue #173)
117
169
 
118
- 2.2.4.1
119
- =======
170
+ 2.2.4.1 (2017-06-17)
171
+ ====================
120
172
 
121
173
  Fixed issue
122
174
  -----------
@@ -130,8 +182,8 @@ differently, it may cause unexpected behavior.
130
182
 
131
183
  ### Fix compilation errors in 2.2.4 on cygwin
132
184
 
133
- 2.2.4
134
- =====
185
+ 2.2.4 (2017-06-11)
186
+ ==================
135
187
 
136
188
  New Features
137
189
  ------------
@@ -169,8 +221,8 @@ Use Win32::Registry instead of Win32API to compile ruby-oci8 on the latest cygwi
169
221
 
170
222
  (contributed by davidbrs. [github issue #156](https://github.com/kubo/ruby-oci8/issues/156))
171
223
 
172
- 2.2.3
173
- =====
224
+ 2.2.3 (2016-12-27)
225
+ ==================
174
226
 
175
227
  New Features
176
228
  ------------
@@ -183,8 +235,8 @@ New Features
183
235
  - Suppress warnings outputted by Minitest in ruby 2.4.0
184
236
  - Suppress warnings when compiling with ruby 2.4.0
185
237
 
186
- 2.2.2
187
- =====
238
+ 2.2.2 (2016-04-24)
239
+ ==================
188
240
 
189
241
  New Features
190
242
  ------------
@@ -230,8 +282,8 @@ Other Changes
230
282
  - Check the default value of DYLD_FALLBACK_LIBRARY_PATH after checking OCI_DIR on installation. (OS X only)
231
283
 
232
284
 
233
- 2.2.1
234
- =====
285
+ 2.2.1 (2015-11-01)
286
+ ==================
235
287
 
236
288
  New Features
237
289
  ------------
@@ -259,16 +311,16 @@ Other Changes
259
311
 
260
312
  - Delete unused code which was added to support old Oracle and ruby 1.8.
261
313
 
262
- 2.2.0.2
263
- =======
314
+ 2.2.0.2 (2015-10-12)
315
+ ====================
264
316
 
265
317
  Nothing was changed except the version.
266
318
 
267
319
  The forth version was incremented to release binary gems for mingw32.
268
320
  The binary gems for 2.2.0.1 didn't work by faultily packaging.
269
321
 
270
- 2.2.0.1
271
- =======
322
+ 2.2.0.1 (2015-10-11)
323
+ ====================
272
324
 
273
325
  If ruby-oci8 2.2.0 is installed, you have no need to update it to
274
326
  2.2.0.1. Source code itself was not changed between 2.2.0 and 2.2.0.1.
@@ -284,8 +336,8 @@ Ruby-oci8 2.2.0 documents had not been generated in rubydoc.info
284
336
  though the URLs are displayed on installation failure. They were
285
337
  changed to documents generated by the latest github repository.
286
338
 
287
- 2.2.0
288
- =====
339
+ 2.2.0 (2015-10-04)
340
+ ==================
289
341
 
290
342
  ### Drop ruby 1.8 support
291
343
 
@@ -326,8 +378,8 @@ Other Changes
326
378
  - Add OCI8.charset_name2id and OCI8.charset_id2name.
327
379
  Mark OCI8#charset_name2id and OCI8#charset_id2name as deprecated.
328
380
 
329
- 2.1.8
330
- =====
381
+ 2.1.8 (2015-04-04)
382
+ ==================
331
383
 
332
384
  New Features
333
385
  ------------
@@ -387,8 +439,8 @@ Fixed Issues
387
439
  - Don't use SYM2ID on ruby 2.2.0 or later not to make symbols unGCable
388
440
  by [Symbol GC](http://www.infoq.com/news/2014/12/ruby-2.2.0-released).
389
441
 
390
- 2.1.7
391
- =====
442
+ 2.1.7 (2014-02-02)
443
+ ==================
392
444
 
393
445
  New Features
394
446
  ------------
@@ -400,8 +452,8 @@ Fixed Issues
400
452
 
401
453
  - Fix OCI8#describe_table to follow synonyms in a remote database.
402
454
 
403
- 2.1.6
404
- =====
455
+ 2.1.6 (2013-12-29)
456
+ ==================
405
457
 
406
458
  New Features
407
459
  ------------
@@ -441,8 +493,8 @@ Fixed Issues
441
493
  - fix SEGV when one connection is used by more than two threads and temporary
442
494
  lobs are freed by GC.
443
495
 
444
- 2.1.5
445
- =====
496
+ 2.1.5 (2013-03-09)
497
+ ==================
446
498
 
447
499
  New Features
448
500
  ------------
@@ -462,8 +514,8 @@ Fixed Issues
462
514
  instant client is 11.2.0.3 for Solaris x86 32-bit, the ruby
463
515
  version is 1.9.3 or upper and the ruby is compiled by gcc.
464
516
 
465
- 2.1.4
466
- =====
517
+ 2.1.4 (2013-01-06)
518
+ ==================
467
519
 
468
520
  New Features
469
521
  ------------
@@ -503,8 +555,8 @@ Fixed Issues
503
555
 
504
556
  (reported by Brian Henderson)
505
557
 
506
- 2.1.3
507
- =====
558
+ 2.1.3 (2012-11-11)
559
+ ==================
508
560
 
509
561
  New Features
510
562
  ------------
@@ -561,8 +613,8 @@ Fixed Issues
561
613
  - Fix #<NoMethodError: undefined method `timezone' for Time:Class>
562
614
  when ruby is less than 1.9.2 and an object type's time attribute is accessed.
563
615
 
564
- 2.1.2
565
- =====
616
+ 2.1.2 (2012-04-28)
617
+ ==================
566
618
 
567
619
  Specification changes
568
620
  ---------------------
@@ -583,8 +635,8 @@ Fixed Issues
583
635
 
584
636
  (reported by Yasuo Honda)
585
637
 
586
- 2.1.1
587
- =====
638
+ 2.1.1 (2012-04-22)
639
+ ==================
588
640
 
589
641
  New Features
590
642
  ------------
@@ -631,8 +683,8 @@ Fixed Issues
631
683
 
632
684
  (repored by Leoš Bitto)
633
685
 
634
- 2.1.0
635
- =====
686
+ 2.1.0 (2011-12-13)
687
+ ==================
636
688
 
637
689
  New Features
638
690
  ------------
@@ -747,8 +799,8 @@ Fixed Issues
747
799
 
748
800
  (reported by jbirdjavi)
749
801
 
750
- 2.0.6
751
- =====
802
+ 2.0.6 (2011-06-14)
803
+ ==================
752
804
 
753
805
  Fixed issues
754
806
  ------------
@@ -759,8 +811,8 @@ Fixed issues
759
811
  a closed OCI handle's method is called. It was chaned in 2.0.5
760
812
  by mistake.
761
813
 
762
- 2.0.5
763
- =====
814
+ 2.0.5 (2011-06-12)
815
+ ==================
764
816
 
765
817
  New Features
766
818
  ------------
@@ -848,8 +900,8 @@ Fixed issues
848
900
 
849
901
  (reported by Sebastian YEPES)
850
902
 
851
- 2.0.4
852
- =====
903
+ 2.0.4 (2010-02-28)
904
+ ==================
853
905
 
854
906
  New Features
855
907
  ------------
@@ -910,8 +962,8 @@ Fixed issues
910
962
 
911
963
  (reported by Raimonds Simanovskis)
912
964
 
913
- 2.0.3
914
- =====
965
+ 2.0.3 (2009-10-21)
966
+ ==================
915
967
 
916
968
  Incompatible Changes
917
969
  --------------------
@@ -1051,8 +1103,8 @@ Fixed installation issues
1051
1103
 
1052
1104
  (reported by Kazuya Teramoto)
1053
1105
 
1054
- 2.0.2
1055
- =====
1106
+ 2.0.2 (2009-05-17)
1107
+ ==================
1056
1108
 
1057
1109
  * add new methods
1058
1110
  - {OCI8#select_one}
@@ -1092,8 +1144,8 @@ Fixed installation issues
1092
1144
  * [ruby 1.9] fix to bind string data by the length got from String#bytesize
1093
1145
  converted to {OCI8.encoding}, not by String#size.
1094
1146
 
1095
- 2.0.1
1096
- =====
1147
+ 2.0.1 (2009-03-17)
1148
+ ==================
1097
1149
 
1098
1150
  * release a binary gem for Windows, which contains libraries for both
1099
1151
  ruby 1.8 and ruby 1.9.1.
data/dist-files CHANGED
@@ -80,7 +80,7 @@ lib/oci8/oracle_version.rb
80
80
  lib/oci8/properties.rb
81
81
  lib/oci8/version.rb
82
82
  lib/ruby-oci8.rb
83
- test/README
83
+ test/README.md
84
84
  test/config.rb
85
85
  test/setup_test_object.sql
86
86
  test/setup_test_package.sql
@@ -110,6 +110,7 @@ Package" or copy a runtime library to the directory where `ruby.exe` resides.
110
110
 
111
111
  | Oracle Version | Package | Runtime Library|
112
112
  |---|---|---|
113
+ | 18.3 | [Microsoft Visual C++ 2013 Redistributable Package][2013] | MSVCR120.DLL |
113
114
  | 12.2.0.x | [Microsoft Visual C++ 2013 Redistributable Package][2013] | MSVCR120.DLL |
114
115
  | 12.1.0.x | [Microsoft Visual C++ 2010 Redistributable Package][2010] | MSVCR100.DLL |
115
116
  | 11.2.0.x | Microsoft Visual C++ 2005 SP1 Redistributable Package ([x86][2005SP1_x86], [x64][2005SP1_x64]) | MSVCR80.DLL(The file version must be 8.0.50727.762.) |
data/lib/oci8.rb CHANGED
@@ -95,7 +95,7 @@ begin
95
95
 
96
96
  ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
97
97
  ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
98
- if dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
98
+ if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
99
99
  dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
100
100
  break
101
101
  end
data/lib/oci8/bindtype.rb CHANGED
@@ -172,20 +172,6 @@ class OCI8
172
172
  end
173
173
  end
174
174
 
175
- class Long < OCI8::BindType::String
176
- def self.create(con, val, param, max_array_size)
177
- param = {:length => con.long_read_len, :char_semantics => true}
178
- super(con, val, param, max_array_size)
179
- end
180
- end
181
-
182
- class LongRaw < OCI8::BindType::RAW
183
- def self.create(con, val, param, max_array_size)
184
- param = {:length => con.long_read_len, :char_semantics => false}
185
- self.new(con, val, param, max_array_size)
186
- end
187
- end
188
-
189
175
  class CLOB
190
176
  def self.create(con, val, param, max_array_size)
191
177
  if param.is_a? OCI8::Metadata::Base and param.charset_form == :nchar
@@ -6,14 +6,24 @@ class OCI8
6
6
  case RUBY_PLATFORM
7
7
  when /mswin32|cygwin|mingw32|bccwin32/
8
8
 
9
- require 'Win32API'
9
+ require 'fiddle/import'
10
+ require 'fiddle/types'
11
+
12
+ extend Fiddle::Importer
13
+ dlload 'kernel32.dll'
14
+ include Fiddle::BasicTypes
15
+ include Fiddle::Win32Types
16
+
17
+ typealias "HANDLE", "void*"
18
+ typealias "HMODULE", "void*"
19
+ extern "DWORD GetModuleFileNameA(HMODULE, LPSTR, DWORD)"
20
+ extern "UINT GetSystemDirectoryA(LPCSTR, UINT)"
21
+ extern "UINT GetWindowsDirectoryA(LPCSTR, UINT)"
22
+ extern "HMODULE LoadLibraryExA(LPCSTR, HANDLE, DWORD)"
23
+ extern "BOOL FreeLibrary(HMODULE)"
24
+
10
25
  MAX_PATH = 260
11
- GetModuleFileNameA = Win32API.new('kernel32.dll', 'GetModuleFileNameA', 'PPL', 'L')
12
- GetSystemDirectoryA = Win32API.new('kernel32.dll', 'GetSystemDirectoryA', 'PL', 'L')
13
- GetWindowsDirectoryA = Win32API.new('kernel32.dll', 'GetWindowsDirectoryA', 'PL', 'L')
14
- LoadLibraryExA = Win32API.new('kernel32.dll', 'LoadLibraryExA', 'PPL', 'P')
15
- FreeLibrary = Win32API.new('kernel32.dll', 'FreeLibrary', 'P', 'L')
16
- LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020
26
+ DONT_RESOLVE_DLL_REFERENCES = 0x00000001
17
27
 
18
28
  def self.check_os_specific_load_error(exc)
19
29
  case exc.message
@@ -23,25 +33,50 @@ class OCI8
23
33
  check_win32_pe_arch(File.join(path, '\OCI.DLL'), "Oracle client")
24
34
  end
25
35
  when /^OCI.DLL: 126\(/, /^126: / # "OCI.DLL: 126(The specified module could not be found.)" in English
26
- handle = LoadLibraryExA.call('OCI.DLL', nil, LOAD_LIBRARY_AS_IMAGE_RESOURCE)
27
- unless handle.null?
28
- FreeLibrary.call(handle)
29
- raise LoadError, <<EOS
30
- OCI.DLL is in the PATH but its dependent modules are not found.
36
+ oci_dll_files = dll_load_path_list.inject([]) do |files, path|
37
+ file = File.join(path, '\OCI.DLL')
38
+ files << file if File.exist?(file)
39
+ files
40
+ end
41
+ if oci_dll_files.empty?
42
+ raise LoadError, "Cannot find OCI.DLL in PATH."
43
+ end
44
+ if oci_dll_files.none? {|file| open(file, 'rb') {true} rescue false}
45
+ raise LoadError, "OCI.DLL in PATH isn't readable."
46
+ end
47
+ first_error = nil
48
+ oci_dll_files.each do |file|
49
+ begin
50
+ check_win32_pe_arch(file, "Oracle client")
51
+ valid_arch = true
52
+ rescue LoadError
53
+ first_error ||= $!
54
+ valid_arch = false
55
+ end
56
+ if valid_arch
57
+ handle = LoadLibraryExA(file, nil, DONT_RESOLVE_DLL_REFERENCES)
58
+ unless handle.null?
59
+ FreeLibrary(handle)
60
+ raise LoadError, <<EOS
61
+ Cannot find DLLs depended by #{file}.
31
62
  See http://www.rubydoc.info/github/kubo/ruby-oci8/file/docs/install-instant-client.md#Windows
32
63
  EOS
64
+ end
65
+ break
66
+ end
33
67
  end
68
+ raise first_error if first_error
34
69
  end
35
70
  end # self.check_os_specific_load_error
36
71
 
37
72
  def self.dll_load_path_list
38
73
  buf = "\0" * MAX_PATH
39
74
  paths = []
40
- paths << buf[0, GetModuleFileNameA.call(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '')
41
- paths << buf[0, GetSystemDirectoryA.call(buf, MAX_PATH)].force_encoding("locale")
42
- paths << buf[0, GetWindowsDirectoryA.call(buf, MAX_PATH)].force_encoding("locale")
75
+ paths << buf[0, GetModuleFileNameA(nil, buf, MAX_PATH)].force_encoding("locale").gsub(/\\[^\\]*$/, '')
76
+ paths << buf[0, GetSystemDirectoryA(buf, MAX_PATH)].force_encoding("locale")
77
+ paths << buf[0, GetWindowsDirectoryA(buf, MAX_PATH)].force_encoding("locale")
43
78
  paths << "."
44
- paths + ENV['PATH'].split(';')
79
+ paths + (ENV['PATH'].split(';').reject {|path| path.empty?})
45
80
  end # self.dll_load_path_list
46
81
 
47
82
  def self.check_win32_pe_arch(filename, package)
data/lib/oci8/cursor.rb CHANGED
@@ -25,7 +25,11 @@ class OCI8
25
25
  @names = nil
26
26
  @con = conn
27
27
  @max_array_size = nil
28
+ @fetch_array_size = nil
29
+ @rowbuf_size = 0
30
+ @rowbuf_index = 0
28
31
  __initialize(conn, sql) # Initialize the internal C structure.
32
+ self.prefetch_rows = conn.instance_variable_get(:@prefetch_rows)
29
33
  end
30
34
 
31
35
  # explicitly indicate the date type of fetched value. run this
@@ -38,7 +42,7 @@ class OCI8
38
42
  # cursor.define(2, Time) # fetch the second column as Time.
39
43
  # cursor.exec()
40
44
  def define(pos, type, length = nil)
41
- bindobj = make_bind_object(:type => type, :length => length)
45
+ bindobj = make_bind_object({:type => type, :length => length}, @fetch_array_size || 1)
42
46
  __define(pos, bindobj)
43
47
  if old = @define_handles[pos - 1]
44
48
  old.send(:free)
@@ -126,6 +130,8 @@ class OCI8
126
130
  when :select_stmt
127
131
  __execute(0)
128
132
  define_columns() if @column_metadata.size == 0
133
+ @rowbuf_size = 0
134
+ @rowbuf_index = 0
129
135
  @column_metadata.size
130
136
  else
131
137
  __execute(1)
@@ -384,6 +390,7 @@ class OCI8
384
390
  # @param [Integer] rows The number of rows to be prefetched
385
391
  def prefetch_rows=(rows)
386
392
  attr_set_ub4(11, rows) # OCI_ATTR_PREFETCH_ROWS(11)
393
+ @prefetch_rows = rows
387
394
  end
388
395
 
389
396
  if OCI8::oracle_client_version >= ORAVER_12_1
@@ -468,7 +475,7 @@ class OCI8
468
475
 
469
476
  private
470
477
 
471
- def make_bind_object(param)
478
+ def make_bind_object(param, fetch_array_size = nil)
472
479
  case param
473
480
  when Hash
474
481
  key = param[:type]
@@ -510,22 +517,37 @@ class OCI8
510
517
  OCI8::BindType::Mapping[key] = bindclass if bindclass
511
518
  end
512
519
  raise "unsupported datatype: #{key}" if bindclass.nil?
513
- bindclass.create(@con, val, param, max_array_size)
520
+ bindclass.create(@con, val, param, fetch_array_size || max_array_size)
514
521
  end
515
522
 
523
+ @@use_array_fetch = false
524
+
516
525
  def define_columns
517
526
  # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5494
518
527
  num_cols = attr_get_ub4(18) # OCI_ATTR_PARAM_COUNT(18)
519
- 1.upto(num_cols) do |i|
520
- parm = __paramGet(i)
521
- define_one_column(i, parm) unless @define_handles[i - 1]
522
- @column_metadata[i - 1] = parm
528
+ @column_metadata = 1.upto(num_cols).collect do |i|
529
+ __paramGet(i)
530
+ end
531
+ if @define_handles.size == 0
532
+ use_array_fetch = @@use_array_fetch
533
+ @column_metadata.each do |md|
534
+ case md.data_type
535
+ when :clob, :blob, :bfile
536
+ # Rows prefetching doesn't work for CLOB, BLOB and BFILE.
537
+ # Use array fetching to get more than one row in a network round trip.
538
+ use_array_fetch = true
539
+ end
540
+ end
541
+ @fetch_array_size = @prefetch_rows if use_array_fetch
542
+ end
543
+ @column_metadata.each_with_index do |md, i|
544
+ define_one_column(i + 1, md) unless @define_handles[i]
523
545
  end
524
546
  num_cols
525
547
  end
526
548
 
527
549
  def define_one_column(pos, param)
528
- bindobj = make_bind_object(param)
550
+ bindobj = make_bind_object(param, @fetch_array_size || 1)
529
551
  __define(pos, bindobj)
530
552
  @define_handles[pos - 1] = bindobj
531
553
  end
@@ -540,22 +562,33 @@ class OCI8
540
562
  end
541
563
  end
542
564
 
565
+ def fetch_row_internal
566
+ if @rowbuf_size && @rowbuf_size == @rowbuf_index
567
+ @rowbuf_size = __fetch(@con, @fetch_array_size || 1)
568
+ @rowbuf_index = 0
569
+ end
570
+ @rowbuf_size
571
+ end
572
+
543
573
  def fetch_one_row_as_array
544
- if __fetch(@con)
545
- @define_handles.collect do |handle|
546
- handle.send(:get_data)
574
+ if fetch_row_internal
575
+ ret = @define_handles.collect do |handle|
576
+ handle.send(:get_data, @rowbuf_index)
547
577
  end
578
+ @rowbuf_index += 1
579
+ ret
548
580
  else
549
581
  nil
550
582
  end
551
583
  end
552
584
 
553
585
  def fetch_one_row_as_hash
554
- if __fetch(@con)
586
+ if fetch_row_internal
555
587
  ret = {}
556
588
  get_col_names.each_with_index do |name, idx|
557
- ret[name] = @define_handles[idx].send(:get_data)
589
+ ret[name] = @define_handles[idx].send(:get_data, @rowbuf_index)
558
590
  end
591
+ @rowbuf_index += 1
559
592
  ret
560
593
  else
561
594
  nil
data/lib/oci8/oci8.rb CHANGED
@@ -169,7 +169,6 @@ class OCI8
169
169
  # @private
170
170
  def parse_internal(sql)
171
171
  cursor = OCI8::Cursor.new(self, sql)
172
- cursor.prefetch_rows = @prefetch_rows if @prefetch_rows
173
172
  cursor
174
173
  end
175
174
 
@@ -305,6 +304,7 @@ class OCI8
305
304
  # @return [Array] an array of first row.
306
305
  def select_one(sql, *bindvars)
307
306
  cursor = self.parse(sql)
307
+ cursor.prefetch_rows = 1
308
308
  begin
309
309
  cursor.exec(*bindvars)
310
310
  row = cursor.fetch
data/lib/oci8/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class OCI8
2
- VERSION = "2.2.6.1"
2
+ VERSION = "2.2.7"
3
3
  end
data/lib/oci8lib_200.so CHANGED
Binary file
data/lib/oci8lib_210.so CHANGED
Binary file
data/lib/oci8lib_220.so CHANGED
Binary file
data/lib/oci8lib_230.so CHANGED
Binary file
data/lib/oci8lib_240.so CHANGED
Binary file
data/lib/oci8lib_250.so CHANGED
Binary file
Binary file
data/ruby-oci8.gemspec CHANGED
@@ -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/test/README.md ADDED
@@ -0,0 +1,40 @@
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;
11
+ ```
12
+ or
13
+ ```sql
14
+ SQL> CREATE USER ruby IDENTIFIED BY oci8
15
+ 2 DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
16
+ ```
17
+ 3. Grant the privilege to connect and execute.
18
+ ```sql
19
+ SQL> GRANT connect, resource, create view, create synonym TO ruby;
20
+ SQL> GRANT execute ON dbms_lock TO ruby;
21
+ ```
22
+ 4. Connect as ruby user.
23
+ ```shell
24
+ $ sqlplus ruby/oci8
25
+ SQL>
26
+ ```
27
+ 5. Create object types
28
+ ```sql
29
+ SQL> @test/setup_test_object.sql
30
+ ```
31
+ 6. change $dbname in test/config.rb.
32
+
33
+ Then run the following command:
34
+ ```shell
35
+ $ make check
36
+ ```
37
+ or
38
+ ```
39
+ $ nmake check (If your compiler is MS Visual C++.)
40
+ ````
data/test/config.rb CHANGED
@@ -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.
data/test/test_oci8.rb CHANGED
@@ -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.
@@ -510,4 +600,25 @@ EOS
510
600
  end
511
601
  assert_equal(ver, @conn.oracle_server_version.to_s)
512
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
513
624
  end # TestOCI8
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-oci8
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.6.1
4
+ version: 2.2.7
5
5
  platform: x64-mingw32
6
6
  authors:
7
7
  - Kubo Takehiro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-16 00:00:00.000000000 Z
11
+ date: 2019-01-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available with Oracle 10g or later including Oracle Instant Client.
@@ -63,7 +63,7 @@ files:
63
63
  - lib/oci8/properties.rb
64
64
  - lib/oci8/version.rb
65
65
  - lib/ruby-oci8.rb
66
- - test/README
66
+ - test/README.md
67
67
  - test/config.rb
68
68
  - test/setup_test_object.sql
69
69
  - test/setup_test_package.sql
@@ -100,6 +100,7 @@ files:
100
100
  - lib/oci8lib_230.so
101
101
  - lib/oci8lib_240.so
102
102
  - lib/oci8lib_250.so
103
+ - lib/oci8lib_260.so
103
104
  homepage: http://www.rubydoc.info/github/kubo/ruby-oci8
104
105
  licenses:
105
106
  - BSD-2-Clause
@@ -108,7 +109,6 @@ post_install_message:
108
109
  rdoc_options: []
109
110
  require_paths:
110
111
  - lib
111
- - ext/oci8
112
112
  required_ruby_version: !ruby/object:Gem::Requirement
113
113
  requirements:
114
114
  - - '>='
data/test/README DELETED
@@ -1,42 +0,0 @@
1
- Before runing unit test:
2
-
3
- 1. connect to Oracle as system:
4
-
5
- $ sqlplus system/<password_of_system>
6
-
7
- 2. create user ruby:
8
-
9
- SQL> CREATE USER ruby IDENTIFIED BY oci8;
10
-
11
- or
12
-
13
- SQL> CREATE USER ruby IDENTIFIED BY oci8
14
- 2 DEFAULT TABLESPACE users TEMPORARY TABLESPACE temp;
15
-
16
- 3. grant the privilege to connect and execute.
17
-
18
- SQL> GRANT connect, resource, create view TO ruby;
19
-
20
- 4. connect to Oracle as sys
21
-
22
- $ sqlplus 'sys/<password_of_sys> as sysdba'
23
-
24
- 5. grant privileges
25
-
26
- SQL> GRANT EXECUTE ON dbms_lock TO ruby;
27
- SQL> GRANT CREATE VIEW TO ruby;
28
-
29
- 6. connect as ruby user.
30
-
31
- $ sqlplus ruby/oci8
32
-
33
- 7. Create object types
34
-
35
- SQL> @test/setup_test_object.sql
36
-
37
- 8. change $dbname if the database
38
-
39
- Then you can run:
40
- $ make check
41
- or
42
- $ nmake check (If your compiler is MS Visual C++.)