ruby-oci8 2.2.6.1-x86-mingw32 → 2.2.10-x86-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +167 -3
- data/NEWS +162 -54
- data/README.md +1 -1
- data/dist-files +1 -2
- data/docs/install-instant-client.md +2 -1
- data/docs/install-on-osx.md +29 -116
- data/lib/oci8/bindtype.rb +0 -14
- data/lib/oci8/check_load_error.rb +51 -16
- data/lib/oci8/cursor.rb +46 -13
- data/lib/oci8/oci8.rb +1 -1
- data/lib/oci8/version.rb +1 -1
- data/lib/oci8.rb +9 -4
- data/lib/oci8lib_250.so +0 -0
- data/lib/oci8lib_260.so +0 -0
- data/lib/oci8lib_270.so +0 -0
- data/lib/oci8lib_300.so +0 -0
- data/lib/oci8lib_310.so +0 -0
- data/ruby-oci8.gemspec +2 -3
- data/setup.rb +11 -2
- data/test/README.md +37 -0
- data/test/config.rb +1 -1
- data/test/test_break.rb +9 -9
- data/test/test_datetime.rb +8 -3
- data/test/test_oci8.rb +154 -43
- data/test/test_oranumber.rb +7 -1
- metadata +38 -65
- data/docs/osx-install-dev-tools.png +0 -0
- data/lib/oci8lib_191.so +0 -0
- data/lib/oci8lib_200.so +0 -0
- data/lib/oci8lib_210.so +0 -0
- data/lib/oci8lib_220.so +0 -0
- data/lib/oci8lib_230.so +0 -0
- data/lib/oci8lib_240.so +0 -0
- data/test/README +0 -42
data/docs/install-on-osx.md
CHANGED
@@ -1,133 +1,46 @@
|
|
1
|
-
# @title Install ruby-oci8 on
|
1
|
+
# @title Install ruby-oci8 on macOS
|
2
2
|
|
3
|
-
Install ruby-oci8 on
|
3
|
+
Install ruby-oci8 on macOS
|
4
4
|
=========================
|
5
5
|
|
6
|
-
|
6
|
+
**Note: Ruby-oci8 doesn't run on Apple Silicon because Oracle instant client
|
7
|
+
for Apple Silicon has not been released yet.**
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
Install C compiler
|
12
|
-
------------------
|
13
|
-
|
14
|
-
You need to install the command line developer tools or the Xcode.
|
15
|
-
(The latter includes the former.)
|
16
|
-
|
17
|
-
Run `"cc --version"` in a terminal to check whether they are installed.
|
18
|
-
|
19
|
-
If the cc version is printed, the tools are installed.
|
20
|
-
|
21
|
-
If the follwoing dialog is displayed, click its Install button to
|
22
|
-
install the tools.
|
23
|
-
You have no need to install the Xcode to compile ruby-oci8.
|
24
|
-
It requires command line tools, not an IDE such as the Xcode.
|
25
|
-
|
26
|
-
![dialog](osx-install-dev-tools.png)
|
9
|
+
Prerequisite
|
10
|
+
------------
|
27
11
|
|
28
|
-
|
29
|
-
please re-run as root via sudo."` is printed, you need to run
|
30
|
-
`"sudo cc --version"`, enter your password, look at the license
|
31
|
-
and type `"agree"`.
|
12
|
+
* Command line tools for Xcode or Xcode (by executing `xcode-select --install`) or [Xcode]
|
32
13
|
|
33
14
|
Install Oracle Instant Client Packages
|
34
15
|
--------------------------------------
|
35
16
|
|
36
|
-
|
37
|
-
|
38
|
-
Download the following packages from [Oracle Technology Network][]
|
39
|
-
|
40
|
-
* Instant Client Package - Basic (`instantclient-basic-macos.x64-12.1.0.2.0.zip`) or Basic Lite (`instantclient-basiclite-macos.x64-12.1.0.2.0.zip`)
|
41
|
-
* Instant Client Package - SDK (`instantclient-sdk-macos.x64-12.1.0.2.0.zip`)
|
42
|
-
* Instant Client Package - SQL*Plus (`instantclient-sqlplus-macos.x64-12.1.0.2.0.zip`) (optionally)
|
43
|
-
|
44
|
-
### Install Oracle Instant Client Packages via Homebrew
|
45
|
-
|
46
|
-
To install `Oracle Instant Client Basic` via [Homebrew][]
|
47
|
-
|
48
|
-
* Copy downloaded zip files to `/Library/Caches/Homebrew`
|
49
|
-
(if the environment variable `HOMEBREW_CACHE`
|
50
|
-
is not set and `$HOME/Library/Caches/Homebrew` doesn't exist.)
|
51
|
-
|
52
|
-
* Run the followining commands:
|
53
|
-
|
54
|
-
brew tap InstantClientTap/instantclient
|
55
|
-
brew install instantclient-basic
|
56
|
-
brew install instantclient-sdk
|
57
|
-
brew install instantclient-sqlplus # (optionally)
|
58
|
-
|
59
|
-
* Set the environment variable `OCI_DIR` while performing the following installation steps
|
60
|
-
if Homebrew is installed outside `/usr/local`.
|
61
|
-
|
62
|
-
export OCI_DIR=$(brew --prefix)/lib
|
63
|
-
|
64
|
-
To install `Oracle Instant Client Basic Lite` via [Homebrew][]
|
65
|
-
|
66
|
-
* Copy downloaded zip files to `/Library/Caches/Homebrew`
|
67
|
-
(if the environment variable `HOMEBREW_CACHE`
|
68
|
-
is not set and `$HOME/Library/Caches/Homebrew` doesn't exist.)
|
69
|
-
|
70
|
-
* Run the followining commands:
|
71
|
-
|
72
|
-
brew tap InstantClientTap/instantclient
|
73
|
-
brew install instantclient-basiclite
|
74
|
-
brew install instantclient-sdk
|
75
|
-
brew install instantclient-sqlplus --with-basiclite # (optionally)
|
76
|
-
|
77
|
-
* Set the environment variable `OCI_DIR` while performing the following installation steps
|
78
|
-
if Homebrew is installed outside `/usr/local`.
|
79
|
-
|
80
|
-
export OCI_DIR=$(brew --prefix)/lib
|
81
|
-
|
82
|
-
### Install Oracle Instant Client Manually
|
83
|
-
|
84
|
-
If you don't use [Homebrew][], do the following:
|
85
|
-
|
86
|
-
Unzip the packages as follows:
|
87
|
-
|
88
|
-
mkdir -p /opt/oracle
|
89
|
-
cd /opt/oracle
|
90
|
-
|
91
|
-
Copy downloaded files to /opt/oracle before running the following commands.
|
92
|
-
|
93
|
-
unzip instantclient-basic-macos.x64-12.1.0.2.0.zip
|
94
|
-
unzip instantclient-sdk-macos.x64-12.1.0.2.0.zip
|
95
|
-
unzip instantclient-sqlplus-macos.x64-12.1.0.2.0.zip
|
96
|
-
|
97
|
-
Make a symbolic link to link the library.
|
98
|
-
|
99
|
-
cd /opt/oracle/instantclient_12_1
|
100
|
-
ln -s libclntsh.dylib.12.1 libclntsh.dylib
|
101
|
-
|
102
|
-
Set the environment variable OCI_DIR while performing the following installation steps.
|
103
|
-
|
104
|
-
export OCI_DIR=/opt/oracle/instantclient_12_1
|
105
|
-
|
106
|
-
Installation
|
107
|
-
------------
|
108
|
-
|
109
|
-
If you get a problem in the following steps, look at {file:docs/report-installation-issue.md}.
|
110
|
-
|
111
|
-
### gem package
|
112
|
-
|
113
|
-
Run the following command.
|
17
|
+
If you have installed [Homebrew], use the following command:
|
114
18
|
|
115
|
-
|
19
|
+
```shell
|
20
|
+
$ brew tap InstantClientTap/instantclient
|
21
|
+
$ brew install instantclient-basic # or instantclient-basiclite
|
22
|
+
$ brew install instantclient-sdk
|
23
|
+
$ brew install instantclient-sqlplus # (optionally)
|
24
|
+
```
|
116
25
|
|
117
|
-
|
26
|
+
Otherwise, look at this [page][OTN] and set the environment variable
|
27
|
+
`OCI_DIR` to point the the directory where instant client is installed.
|
28
|
+
Ruby-oci8 installation script checks the directory.
|
118
29
|
|
119
|
-
|
30
|
+
```shell
|
31
|
+
export OCI_DIR=$HOME/Downloads/instantclient_19_8 # for example
|
32
|
+
```
|
120
33
|
|
121
|
-
|
34
|
+
Install ruby-oci8
|
35
|
+
-----------------
|
122
36
|
|
123
|
-
|
37
|
+
Note that `/usr/bin/ruby` isn't available. You need to use [`rbenv`] or so.
|
124
38
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
make install
|
39
|
+
```shell
|
40
|
+
$ gem install ruby-oci8
|
41
|
+
```
|
129
42
|
|
130
|
-
[download page]: https://bintray.com/kubo/generic/ruby-oci8
|
131
43
|
[Homebrew]: http://brew.sh/
|
132
|
-
[
|
133
|
-
[
|
44
|
+
[OTN]: https://www.oracle.com/database/technologies/instant-client/macos-intel-x86-downloads.html#ic_osx_inst
|
45
|
+
[Xcode]: https://apps.apple.com/us/app/xcode/id497799835
|
46
|
+
[`rbenv`]: https://github.com/rbenv/rbenv
|
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 '
|
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
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
41
|
-
paths << buf[0, GetSystemDirectoryA
|
42
|
-
paths << buf[0, GetWindowsDirectoryA
|
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
|
-
|
521
|
-
|
522
|
-
|
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
|
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
|
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
data/lib/oci8.rb
CHANGED
@@ -11,8 +11,11 @@ if RUBY_PLATFORM =~ /cygwin/
|
|
11
11
|
# Cygwin manages environment variables by itself.
|
12
12
|
# They don't synchroize with Win32's ones.
|
13
13
|
# This set some Oracle's environment variables to win32's enviroment.
|
14
|
-
require '
|
15
|
-
win32setenv =
|
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
|
+
|
16
19
|
['NLS_LANG', 'TNS_ADMIN', 'LOCAL'].each do |name|
|
17
20
|
val = ENV[name]
|
18
21
|
win32setenv.call(name, val && val.dup)
|
@@ -63,6 +66,8 @@ when 'rbx'
|
|
63
66
|
so_basename += 'rbx'
|
64
67
|
when 'jruby'
|
65
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'
|
66
71
|
else
|
67
72
|
raise 'unsupported ruby engine: ' + RUBY_ENGINE
|
68
73
|
end
|
@@ -95,7 +100,7 @@ begin
|
|
95
100
|
|
96
101
|
ruby_arch = [nil].pack('P').size == 8 ? :x64 : :x86
|
97
102
|
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
98
|
-
if dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
|
103
|
+
if !path.empty? && dll_arch.call(File.join(path, 'OCI.DLL')) == ruby_arch
|
99
104
|
dll_dir = RubyInstaller::Runtime.add_dll_directory(path)
|
100
105
|
break
|
101
106
|
end
|
@@ -105,7 +110,7 @@ end
|
|
105
110
|
|
106
111
|
begin
|
107
112
|
require so_basename
|
108
|
-
rescue LoadError
|
113
|
+
rescue LoadError
|
109
114
|
require 'oci8/check_load_error'
|
110
115
|
OCI8::Util::check_load_error($!)
|
111
116
|
raise
|
data/lib/oci8lib_250.so
CHANGED
Binary file
|
data/lib/oci8lib_260.so
ADDED
Binary file
|
data/lib/oci8lib_270.so
ADDED
Binary file
|
data/lib/oci8lib_300.so
ADDED
Binary file
|
data/lib/oci8lib_310.so
ADDED
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'
|
@@ -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.
|
53
|
+
so_files << map_file if File.exist? map_file
|
55
54
|
end
|
56
55
|
|
57
56
|
# least version in so_vers
|
@@ -79,7 +78,7 @@ EOS
|
|
79
78
|
end
|
80
79
|
files << 'lib/oci8.rb'
|
81
80
|
end
|
82
|
-
s.require_paths = ['lib'
|
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,
|
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
@@ -134,7 +134,7 @@ class Minitest::Test
|
|
134
134
|
|
135
135
|
def get_oci8_connection()
|
136
136
|
OCI8.new($dbuser, $dbpass, $dbname)
|
137
|
-
|
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_break.rb
CHANGED
@@ -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
|
-
|
26
|
-
|
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
|
@@ -100,6 +99,11 @@ class TestBreak < Minitest::Test
|
|
100
99
|
def test_timeout
|
101
100
|
@conn.non_blocking = true
|
102
101
|
start_time = Time.now
|
102
|
+
if server_is_runing_on_windows?
|
103
|
+
end_time = start_time + 5
|
104
|
+
else
|
105
|
+
end_time = start_time + 1
|
106
|
+
end
|
103
107
|
|
104
108
|
if defined? Rubinius and Rubinius::VERSION < "2.0"
|
105
109
|
# Rubinius 1.2.4
|
@@ -113,12 +117,8 @@ class TestBreak < Minitest::Test
|
|
113
117
|
@conn.exec("BEGIN DBMS_LOCK.SLEEP(5); END;")
|
114
118
|
end
|
115
119
|
end
|
116
|
-
if server_is_runing_on_windows?
|
117
|
-
end_time = start_time + 5
|
118
|
-
else
|
119
|
-
end_time = start_time + 1
|
120
|
-
end
|
121
120
|
assert_in_delta(Time.now, end_time, 1)
|
121
|
+
sleep(0.01) # for truffleruby. Is truffleruby too fast?
|
122
122
|
@conn.exec("BEGIN NULL; END;")
|
123
123
|
assert_in_delta(Time.now, end_time, 1)
|
124
124
|
end
|
data/test/test_datetime.rb
CHANGED
@@ -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
|
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
|
102
|
+
assert_equal(Time.local(*string_to_array(date)), row[0])
|
98
103
|
end
|
99
104
|
end
|
100
105
|
end
|