ruby-oci8 2.0.4 → 2.0.5
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.
- data/ChangeLog +158 -1
- data/Makefile +1 -3
- data/NEWS +70 -0
- data/VERSION +1 -1
- data/dist-files +1 -0
- data/ext/oci8/apiwrap.yml +284 -138
- data/ext/oci8/attr.c +1 -1
- data/ext/oci8/bind.c +36 -9
- data/ext/oci8/env.c +59 -33
- data/ext/oci8/error.c +4 -0
- data/ext/oci8/extconf.rb +15 -1
- data/ext/oci8/lob.c +44 -0
- data/ext/oci8/metadata.c +1 -1
- data/ext/oci8/object.c +55 -0
- data/ext/oci8/oci8.c +9 -14
- data/ext/oci8/oci8.h +39 -25
- data/ext/oci8/oci8lib.c +38 -3
- data/ext/oci8/ocidatetime.c +69 -80
- data/ext/oci8/ocihandle.c +9 -1
- data/ext/oci8/ocinumber.c +40 -18
- data/ext/oci8/oraconf.rb +126 -126
- data/ext/oci8/oradate.c +2 -2
- data/ext/oci8/oranumber_util.c +38 -1
- data/ext/oci8/stmt.c +28 -22
- data/ext/oci8/win32.c +9 -3
- data/lib/oci8.rb.in +13 -2
- data/lib/oci8/.document +1 -0
- data/lib/oci8/bindtype.rb +16 -3
- data/lib/oci8/datetime.rb +14 -6
- data/lib/oci8/encoding-init.rb +6 -1
- data/lib/oci8/encoding.yml +2 -2
- data/lib/oci8/object.rb +28 -9
- data/lib/oci8/oci8.rb +22 -6
- data/lib/oci8/properties.rb +50 -0
- data/test/test_break.rb +6 -7
- data/test/test_oranumber.rb +96 -5
- metadata +7 -4
data/lib/oci8/encoding-init.rb
CHANGED
@@ -5,7 +5,8 @@
|
|
5
5
|
# try to get NLS_LANG.
|
6
6
|
nls_lang = ENV['NLS_LANG']
|
7
7
|
|
8
|
-
if
|
8
|
+
# if NLS_LANG is not set, get it from the Windows registry.
|
9
|
+
if nls_lang.nil? and defined? OCI8::Win32Util
|
9
10
|
dll_path = OCI8::Win32Util.dll_path.upcase
|
10
11
|
if dll_path =~ %r{\\BIN\\OCI.DLL}
|
11
12
|
oracle_home = $`
|
@@ -33,6 +34,10 @@ if nls_lang
|
|
33
34
|
if enc.nil?
|
34
35
|
raise "Ruby encoding name is not found in encoding.yml for NLS_LANG #{nls_lang}."
|
35
36
|
end
|
37
|
+
if enc.is_a? Array
|
38
|
+
# Use the first available encoding in the array.
|
39
|
+
enc = enc.find do |e| Encoding.find(e) rescue false; end
|
40
|
+
end
|
36
41
|
else
|
37
42
|
warn "Warning: NLS_LANG is not set. fallback to US-ASCII."
|
38
43
|
enc = 'US-ASCII'
|
data/lib/oci8/encoding.yml
CHANGED
@@ -40,7 +40,7 @@ ZHS16GBK: GBK
|
|
40
40
|
# MS Windows Code Page 950 with Hong Kong Supplementary Character
|
41
41
|
# Set HKSCS-2001 (character set conversion to and from Unicode is
|
42
42
|
# based on Unicode 3.0)
|
43
|
-
ZHT16HKSCS: Big5
|
43
|
+
ZHT16HKSCS: [Big5-HKSCS, Big5]
|
44
44
|
|
45
45
|
# MS Windows Code Page 950 Traditional Chinese
|
46
46
|
ZHT16MSWIN950: Big5
|
@@ -166,7 +166,7 @@ ZHT16DBT: nil # FIXME
|
|
166
166
|
# MS Windows Code Page 950 with Hong Kong Supplementary Character
|
167
167
|
# Set HKSCS-2001 (character set conversion to and from Unicode is
|
168
168
|
# based on Unicode 3.1)
|
169
|
-
ZHT16HKSCS31: Big5
|
169
|
+
ZHT16HKSCS31: [Big5-HKSCS, Big5]
|
170
170
|
|
171
171
|
# SOPS 32-bit Traditional Chinese
|
172
172
|
ZHT32SOPS: nil # FIXME
|
data/lib/oci8/object.rb
CHANGED
@@ -394,7 +394,7 @@ EOS
|
|
394
394
|
@class_methods[type_method.name.downcase.intern] = result_type
|
395
395
|
end
|
396
396
|
else
|
397
|
-
warn "unsupported return type (#{schema_name}.#{name}.#{type_method.name})" if $VERBOSE
|
397
|
+
warn "unsupported return type (#{metadata.schema_name}.#{metadata.name}.#{type_method.name})" if $VERBOSE
|
398
398
|
end
|
399
399
|
end
|
400
400
|
end
|
@@ -457,6 +457,16 @@ EOS
|
|
457
457
|
#[ATTR_NAMED_COLLECTION, [datatype, typeinfo], SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER]
|
458
458
|
tdo = con.get_tdo_by_metadata(metadata.type_metadata)
|
459
459
|
[ATTR_NAMED_COLLECTION, tdo, tdo.val_size, tdo.ind_size, tdo.alignment]
|
460
|
+
when :clob
|
461
|
+
if metadata.charset_form != :nchar
|
462
|
+
[ATTR_CLOB, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER]
|
463
|
+
else
|
464
|
+
[ATTR_NCLOB, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER]
|
465
|
+
end
|
466
|
+
when :blob
|
467
|
+
[ATTR_BLOB, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER]
|
468
|
+
when :bfile
|
469
|
+
[ATTR_BFILE, con, SIZE_OF_POINTER, 2, ALIGNMENT_OF_POINTER]
|
460
470
|
else
|
461
471
|
raise "unsupported typecode #{metadata.typecode}"
|
462
472
|
end
|
@@ -487,6 +497,7 @@ EOS
|
|
487
497
|
|
488
498
|
class NamedType
|
489
499
|
def to_value
|
500
|
+
return nil if self.null?
|
490
501
|
obj = tdo.ruby_class.new
|
491
502
|
obj.instance_variable_set(:@attributes, self.attributes)
|
492
503
|
obj
|
@@ -503,20 +514,28 @@ EOS
|
|
503
514
|
end
|
504
515
|
|
505
516
|
def attributes=(obj)
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
517
|
+
if obj.nil?
|
518
|
+
self.null = true
|
519
|
+
else
|
520
|
+
obj = obj.instance_variable_get(:@attributes) unless obj.is_a? Hash
|
521
|
+
tdo.attributes.each do |attr|
|
522
|
+
attr_val = obj[attr.name]
|
523
|
+
attr_val = attr.set_proc.call(attr_val) if attr.set_proc
|
524
|
+
set_attribute(attr.datatype, attr.typeinfo, attr.val_offset, attr.ind_offset, attr_val)
|
525
|
+
end
|
526
|
+
self.null = false
|
511
527
|
end
|
512
528
|
end
|
513
529
|
end
|
514
530
|
|
515
531
|
class NamedCollection
|
516
532
|
def to_value
|
517
|
-
|
518
|
-
|
519
|
-
|
533
|
+
attr = self.attributes
|
534
|
+
if attr
|
535
|
+
obj = tdo.ruby_class.new
|
536
|
+
obj.instance_variable_set(:@attributes, attr)
|
537
|
+
obj
|
538
|
+
end
|
520
539
|
end
|
521
540
|
|
522
541
|
def attributes
|
data/lib/oci8/oci8.rb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#
|
9
9
|
|
10
10
|
require 'date'
|
11
|
+
require 'yaml'
|
11
12
|
|
12
13
|
# A connection to a Oracle database server.
|
13
14
|
#
|
@@ -543,13 +544,28 @@ class OraDate
|
|
543
544
|
end
|
544
545
|
|
545
546
|
class OraNumber
|
546
|
-
def yaml_initialize(type, val) # :nodoc:
|
547
|
-
initialize(val)
|
548
|
-
end
|
549
547
|
|
550
|
-
|
551
|
-
|
552
|
-
|
548
|
+
if defined? Psych and YAML == Psych
|
549
|
+
|
550
|
+
yaml_tag '!ruby/object:OraNumber'
|
551
|
+
def encode_with coder # :nodoc:
|
552
|
+
coder.scalar = self.to_s
|
553
|
+
end
|
554
|
+
|
555
|
+
def init_with coder # :nodoc:
|
556
|
+
initialize(coder.scalar)
|
557
|
+
end
|
558
|
+
|
559
|
+
else
|
560
|
+
|
561
|
+
def yaml_initialize(type, val) # :nodoc:
|
562
|
+
initialize(val)
|
563
|
+
end
|
564
|
+
|
565
|
+
def to_yaml(opts = {}) # :nodoc:
|
566
|
+
YAML.quick_emit(object_id, opts) do |out|
|
567
|
+
out.scalar(taguri, self.to_s, :plain)
|
568
|
+
end
|
553
569
|
end
|
554
570
|
end
|
555
571
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# properties.rb -- implements OCI8.properties
|
2
|
+
#
|
3
|
+
# Copyright (C) 2010 KUBO Takehiro <kubo@jiubao.org>
|
4
|
+
|
5
|
+
class OCI8
|
6
|
+
|
7
|
+
@@properties = {
|
8
|
+
:bind_string_as_nchar => false,
|
9
|
+
}
|
10
|
+
|
11
|
+
def @@properties.[](name)
|
12
|
+
raise IndexError, "No such property name: #{name}" unless @@properties.has_key?(name)
|
13
|
+
super(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def @@properties.[]=(name, val)
|
17
|
+
raise IndexError, "No such property name: #{name}" unless @@properties.has_key?(name)
|
18
|
+
case name
|
19
|
+
when :bind_string_as_nchar
|
20
|
+
val = val ? true : false
|
21
|
+
end
|
22
|
+
super(name, val)
|
23
|
+
end
|
24
|
+
|
25
|
+
# call-seq:
|
26
|
+
# OCI8.properties -> a customized Hash
|
27
|
+
#
|
28
|
+
# (new in 2.0.5)
|
29
|
+
#
|
30
|
+
# Returns a Hash which ruby-oci8 global settings.
|
31
|
+
# The hash's setter and getter methods are customized to check
|
32
|
+
# property names and values.
|
33
|
+
#
|
34
|
+
# # get properties
|
35
|
+
# OCI8.properties[:bind_string_as_nchar] # => false
|
36
|
+
# OCI8.properties[:invalid_property_name] # raises an IndexError
|
37
|
+
#
|
38
|
+
# # set properties
|
39
|
+
# OCI8.properties[:bind_string_as_nchar] = true
|
40
|
+
# OCI8.properties[:invalid_property_name] = true # raises an IndexError
|
41
|
+
#
|
42
|
+
# Supported properties are listed below:
|
43
|
+
#
|
44
|
+
# [:bind_string_as_nchar]
|
45
|
+
# +true+ when string bind variables are bound as NCHAR,
|
46
|
+
# otherwise +false+. The default value is +false+.
|
47
|
+
def self.properties
|
48
|
+
@@properties
|
49
|
+
end
|
50
|
+
end
|
data/test/test_break.rb
CHANGED
@@ -23,23 +23,22 @@ class TestBreak < Test::Unit::TestCase
|
|
23
23
|
|
24
24
|
TIME_IN_PLSQL = 5
|
25
25
|
TIME_TO_BREAK = 2
|
26
|
-
MARGIN = 0.1
|
27
26
|
|
28
27
|
def do_test_ocibreak(conn, expect)
|
29
28
|
$start_time = Time.now
|
30
29
|
|
31
30
|
th = Thread.start do
|
32
31
|
begin
|
33
|
-
|
34
|
-
|
32
|
+
conn.exec("BEGIN DBMS_LOCK.SLEEP(#{TIME_IN_PLSQL}); END;")
|
33
|
+
assert_equal(expect[PLSQL_DONE], (Time.now - $start_time).round, 'PLSQL_DONE')
|
35
34
|
rescue OCIBreak
|
36
|
-
|
35
|
+
assert_equal(expect[OCIBREAK], (Time.now - $start_time).round, 'OCIBREAK')
|
37
36
|
end
|
38
37
|
end
|
39
38
|
|
40
|
-
sleep(0.
|
41
|
-
sleep(TIME_TO_BREAK)
|
42
|
-
assert_equal(expect[SEND_BREAK], (Time.now - $start_time
|
39
|
+
sleep(0.3) # Wait until DBMS_LOCK.SLEEP is running.
|
40
|
+
sleep(TIME_TO_BREAK - 0.3)
|
41
|
+
assert_equal(expect[SEND_BREAK], (Time.now - $start_time).round, 'SEND_BREAK')
|
43
42
|
conn.break()
|
44
43
|
th.join
|
45
44
|
end
|
data/test/test_oranumber.rb
CHANGED
@@ -125,6 +125,33 @@ class TestOraNumber < Test::Unit::TestCase
|
|
125
125
|
val = $1+'.'+$2 if /(-?)0\.(.*)/ =~ val
|
126
126
|
assert_equal(val, cursor[:out])
|
127
127
|
end
|
128
|
+
# Infinity and -Infinity
|
129
|
+
['~', '-~'].each do |val|
|
130
|
+
cursor[:in] = OraNumber.new(val)
|
131
|
+
cursor.exec
|
132
|
+
assert_equal(val, cursor[:out])
|
133
|
+
end
|
134
|
+
if OCI8::oracle_client_version >= OCI8::ORAVER_10_1
|
135
|
+
cursor = conn.parse(<<EOS)
|
136
|
+
BEGIN
|
137
|
+
IF (:in_oranum = CAST(:in_binary_double AS NUMBER)) THEN
|
138
|
+
:result := 'match';
|
139
|
+
ELSE
|
140
|
+
:result := 'unmatch';
|
141
|
+
END IF;
|
142
|
+
END;
|
143
|
+
EOS
|
144
|
+
cursor.bind_param(:in_oranum, nil, OraNumber)
|
145
|
+
cursor.bind_param(:in_binary_double, nil, :binary_double)
|
146
|
+
cursor.bind_param(:result, nil, String, 7)
|
147
|
+
[['~', 1.0/0.0], ['-~', -1.0/0.0]].each do |val|
|
148
|
+
cursor[:in_oranum] = OraNumber.new(val[0])
|
149
|
+
cursor[:in_binary_double] = val[1]
|
150
|
+
cursor.exec
|
151
|
+
assert_equal(cursor[:result], 'match')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
128
155
|
ensure
|
129
156
|
conn.logoff
|
130
157
|
end
|
@@ -142,13 +169,39 @@ class TestOraNumber < Test::Unit::TestCase
|
|
142
169
|
cursor.exec
|
143
170
|
assert_equal(OraNumber.new(val), cursor[:out])
|
144
171
|
end
|
172
|
+
# Infinity and -Infinity
|
173
|
+
if OCI8::oracle_client_version >= OCI8::ORAVER_10_1
|
174
|
+
cursor = conn.parse("BEGIN :out := CAST(:in AS NUMBER); END;")
|
175
|
+
cursor.bind_param(:out, OraNumber)
|
176
|
+
cursor.bind_param(:in, nil, :binary_double)
|
177
|
+
[['~', 1.0/0.0], ['-~', -1.0/0.0]].each do |val|
|
178
|
+
cursor[:in] = val[1]
|
179
|
+
cursor.exec
|
180
|
+
assert_equal(OraNumber.new(val[0]), cursor[:out])
|
181
|
+
end
|
182
|
+
end
|
183
|
+
ensure
|
184
|
+
conn.logoff
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def test_bind_basic_number_type
|
189
|
+
conn = get_oci8_connection
|
190
|
+
bind_type = OCI8::BindType::Mapping[:number]
|
191
|
+
begin
|
192
|
+
OCI8::BindType::Mapping[:number] = OCI8::BindType::BasicNumberType
|
193
|
+
assert_kind_of(NilClass, conn.select_one('select CAST(NULL AS NUMBER) from dual')[0])
|
194
|
+
assert_kind_of(Integer, conn.select_one('select 0.0 from dual')[0])
|
195
|
+
assert_kind_of(Integer, conn.select_one('select 10.0 from dual')[0])
|
196
|
+
assert_kind_of(Float, conn.select_one('select 10.1 from dual')[0])
|
145
197
|
ensure
|
146
198
|
conn.logoff
|
199
|
+
OCI8::BindType::Mapping[:number] = bind_type
|
147
200
|
end
|
148
201
|
end
|
149
202
|
|
150
203
|
def test_dup
|
151
|
-
LARGE_RANGE_VALUES.each do |x|
|
204
|
+
(LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
|
152
205
|
n = OraNumber.new(x)
|
153
206
|
assert_equal(n, n.dup)
|
154
207
|
assert_equal(n, n.clone)
|
@@ -156,14 +209,14 @@ class TestOraNumber < Test::Unit::TestCase
|
|
156
209
|
end
|
157
210
|
|
158
211
|
def test_marshal
|
159
|
-
LARGE_RANGE_VALUES.each do |x|
|
212
|
+
(LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
|
160
213
|
n = OraNumber.new(x)
|
161
214
|
assert_equal(n, Marshal.load(Marshal.dump(n)))
|
162
215
|
end
|
163
216
|
end
|
164
217
|
|
165
218
|
def test_yaml
|
166
|
-
LARGE_RANGE_VALUES.each do |x|
|
219
|
+
(LARGE_RANGE_VALUES + ['~', '-~']).each do |x|
|
167
220
|
n = OraNumber.new(x)
|
168
221
|
assert_equal(n, YAML.load(YAML.dump(n)))
|
169
222
|
end
|
@@ -200,11 +253,28 @@ class TestOraNumber < Test::Unit::TestCase
|
|
200
253
|
|
201
254
|
# OCI8::Math.atan2(y, x) -> ocinumber
|
202
255
|
def test_math_atan2
|
256
|
+
# Prior to ruby 1.9.2:
|
257
|
+
# Following method calls' return values depend on the underneath C library
|
258
|
+
# implementation.
|
259
|
+
#
|
260
|
+
# Math::atan2(+0.0, +0.0)
|
261
|
+
# Math::atan2(-0.0, +0.0)
|
262
|
+
# Math::atan2(+0.0, -0.0)
|
263
|
+
# Math::atan2(-0.0, -0.0)
|
264
|
+
#
|
265
|
+
# They are +0.0, -0.0, +PI and -PI respectively as far as I checked them on
|
266
|
+
# Windows and Linux.
|
267
|
+
#
|
268
|
+
# After ruby 1.9.2:
|
269
|
+
# They all raise a Math::DomainError exception.
|
270
|
+
#
|
271
|
+
# In contrast to Math::atan2, OCI8::Math::atan2(0, 0) allways returns 0 because
|
272
|
+
# OraNumber doesn't have the difference between +0 and -0.
|
203
273
|
compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
|
204
|
-
Proc.new {|x, y| Math::atan2(x, y.to_f)},
|
274
|
+
Proc.new {|x, y| (x.to_f == 0 && y.to_f == 0) ? 0 : Math::atan2(x, y.to_f)},
|
205
275
|
Proc.new {|x, y| OCI8::Math::atan2(x, y.to_f)})
|
206
276
|
compare_with_float2(SMALL_RANGE_VALUES, SMALL_RANGE_VALUES,
|
207
|
-
Proc.new {|x, y| Math::atan2(y.to_f, x)},
|
277
|
+
Proc.new {|x, y| (x.to_f == 0 && y.to_f == 0) ? 0 : Math::atan2(y.to_f, x)},
|
208
278
|
Proc.new {|x, y| OCI8::Math::atan2(y.to_f, x)})
|
209
279
|
end
|
210
280
|
|
@@ -652,4 +722,25 @@ class TestOraNumber < Test::Unit::TestCase
|
|
652
722
|
assert_equal(ary[1], OraNumber.new(ary[0]).to_s)
|
653
723
|
end
|
654
724
|
end
|
725
|
+
|
726
|
+
def test_dump
|
727
|
+
conn = get_oci8_connection
|
728
|
+
begin
|
729
|
+
cursor = conn.parse("select dump(to_number(:1)) from dual")
|
730
|
+
cursor.bind_param(1, nil, String, 40)
|
731
|
+
LARGE_RANGE_VALUES.each do |val|
|
732
|
+
cursor[1] = val
|
733
|
+
cursor.exec
|
734
|
+
assert_equal(cursor.fetch[0], OraNumber.new(val).dump)
|
735
|
+
end
|
736
|
+
ensure
|
737
|
+
conn.logoff
|
738
|
+
end
|
739
|
+
LARGE_RANGE_VALUES
|
740
|
+
end
|
741
|
+
|
742
|
+
def test_has_decimal_part
|
743
|
+
assert_equal(false, OraNumber(10.0).has_decimal_part?)
|
744
|
+
assert_equal(true, OraNumber(10.1).has_decimal_part?)
|
745
|
+
end
|
655
746
|
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 2
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 2.0.
|
8
|
+
- 5
|
9
|
+
version: 2.0.5
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- KUBO Takehiro
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date:
|
17
|
+
date: 2011-06-12 00:00:00 +09:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/oci8/object.rb
|
87
87
|
- lib/oci8/oci8.rb
|
88
88
|
- lib/oci8/oracle_version.rb
|
89
|
+
- lib/oci8/properties.rb
|
89
90
|
- test/README
|
90
91
|
- test/config.rb
|
91
92
|
- test/test_all.rb
|
@@ -117,6 +118,7 @@ rdoc_options:
|
|
117
118
|
require_paths:
|
118
119
|
- lib
|
119
120
|
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
120
122
|
requirements:
|
121
123
|
- - ">="
|
122
124
|
- !ruby/object:Gem::Version
|
@@ -126,6 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
126
128
|
- 0
|
127
129
|
version: 1.8.0
|
128
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
+
none: false
|
129
132
|
requirements:
|
130
133
|
- - ">="
|
131
134
|
- !ruby/object:Gem::Version
|
@@ -135,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
135
138
|
requirements: []
|
136
139
|
|
137
140
|
rubyforge_project: ruby-oci8
|
138
|
-
rubygems_version: 1.3.
|
141
|
+
rubygems_version: 1.3.7
|
139
142
|
signing_key:
|
140
143
|
specification_version: 3
|
141
144
|
summary: Ruby interface for Oracle using OCI8 API
|