ruby-oci8 2.1.5.1-x64-mingw32 → 2.1.7-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +123 -0
- data/NEWS +54 -0
- data/README.md +9 -6
- data/VERSION +1 -1
- data/docs/install-full-client.md +2 -4
- data/docs/install-instant-client.md +14 -9
- data/docs/report-installation-issue.md +1 -1
- data/lib/oci8.rb +10 -19
- data/lib/oci8.rb.in +8 -17
- data/lib/oci8/cursor.rb +2 -0
- data/lib/oci8/metadata.rb +87 -9
- data/lib/oci8/object.rb +23 -0
- data/lib/oci8lib_200.so +0 -0
- data/lib/oci8lib_210.so +0 -0
- data/ruby-oci8.gemspec +1 -1
- data/test/config.rb +76 -66
- data/test/test_all.rb +4 -6
- data/test/test_appinfo.rb +2 -3
- data/test/test_array_dml.rb +6 -7
- data/test/test_bind_raw.rb +1 -2
- data/test/test_bind_string.rb +1 -2
- data/test/test_bind_time.rb +1 -2
- data/test/test_break.rb +2 -3
- data/test/test_clob.rb +1 -2
- data/test/test_connection_pool.rb +2 -3
- data/test/test_connstr.rb +1 -4
- data/test/test_datetime.rb +2 -3
- data/test/test_dbi.rb +1 -2
- data/test/test_dbi_clob.rb +6 -6
- data/test/test_encoding.rb +1 -2
- data/test/test_error.rb +1 -2
- data/test/test_metadata.rb +2086 -898
- data/test/test_object.rb +8 -11
- data/test/test_oci8.rb +1 -2
- data/test/test_oracle_version.rb +1 -3
- data/test/test_oradate.rb +1 -2
- data/test/test_oranumber.rb +5 -6
- data/test/test_rowid.rb +1 -2
- metadata +6 -5
data/lib/oci8/metadata.rb
CHANGED
@@ -89,6 +89,15 @@ class OCI8
|
|
89
89
|
# attr_get_oradate(OCI_ATTR_TIMESTAMP)
|
90
90
|
#end
|
91
91
|
|
92
|
+
# Returns the database link name if the object is at the remote host.
|
93
|
+
# Note that this is available only when the object is returned by OCI8#describe_* methods.
|
94
|
+
#
|
95
|
+
# @return [String or nil] database link name
|
96
|
+
# @since 2.1.7
|
97
|
+
def obj_link
|
98
|
+
@obj_link
|
99
|
+
end
|
100
|
+
|
92
101
|
# @private
|
93
102
|
def inspect
|
94
103
|
"#<#{self.class.name}:(#{obj_id}) #{obj_schema}.#{obj_name}>"
|
@@ -110,7 +119,7 @@ class OCI8
|
|
110
119
|
Proc.new do |p|
|
111
120
|
if p.charset_form == :nchar
|
112
121
|
"NVARCHAR2(#{p.char_size})"
|
113
|
-
elsif p.char_used?
|
122
|
+
elsif p.respond_to?(:char_used?) && p.char_used?
|
114
123
|
"VARCHAR2(#{p.char_size} CHAR)"
|
115
124
|
else
|
116
125
|
"VARCHAR2(#{p.data_size})"
|
@@ -248,6 +257,12 @@ class OCI8
|
|
248
257
|
"TIMESTAMP(#{fsprecision}) WITH LOCAL TIME ZONE"
|
249
258
|
end
|
250
259
|
end]
|
260
|
+
DATA_TYPE_MAP[245] = [:record,
|
261
|
+
Proc.new do |p|
|
262
|
+
"#{p.schema_name}.#{p.type_name}"
|
263
|
+
end]
|
264
|
+
DATA_TYPE_MAP[252] = [:boolean, "BOOLEAN"]
|
265
|
+
DATA_TYPE_MAP[266] = [:pls_integer, "PLS_INTEGER"]
|
251
266
|
|
252
267
|
def __data_type # :nodoc:
|
253
268
|
return @data_type if defined? @data_type
|
@@ -337,6 +352,9 @@ class OCI8
|
|
337
352
|
#when 228; :sysfirst # OCI_TYPECODE_SYSFIRST
|
338
353
|
#when 235; :syslast # OCI_TYPECODE_SYSLAST
|
339
354
|
when 266; :pls_integer # OCI_TYPECODE_PLS_INTEGER
|
355
|
+
when 250; :record # OCI_TYPECODE_RECORD
|
356
|
+
when 251; :itable # OCI_TYPECODE_ITABLE
|
357
|
+
when 252; :boolean # OCI_TYPECODE_BOOLEAN
|
340
358
|
end
|
341
359
|
end
|
342
360
|
end
|
@@ -632,6 +650,12 @@ class OCI8
|
|
632
650
|
end
|
633
651
|
private :list_subprograms
|
634
652
|
|
653
|
+
# package type list
|
654
|
+
def list_types # :nodoc:
|
655
|
+
__param(137) # OCI_ATTR_LIST_PKG_TYPES
|
656
|
+
end
|
657
|
+
private :list_types
|
658
|
+
|
635
659
|
# Returns +true+ if the package subprograms have
|
636
660
|
# {invoker's rights}[http://download.oracle.com/docs/cd/B28359_01/appdev.111/b28370/subprograms.htm#i18574].
|
637
661
|
# Otherwise, +false+.
|
@@ -647,6 +671,22 @@ class OCI8
|
|
647
671
|
prog.instance_variable_set(:@is_standalone, false)
|
648
672
|
end
|
649
673
|
end
|
674
|
+
|
675
|
+
if OCI8.oracle_client_version < ORAVER_12_1
|
676
|
+
def types
|
677
|
+
raise "This version of the Oracle client does not support PL/SQL package type descriptions."
|
678
|
+
end
|
679
|
+
else
|
680
|
+
# Returns an array of types defined within the Package.
|
681
|
+
#
|
682
|
+
# @return [array of OCI8::Metadata::Type]
|
683
|
+
# @since 2.1.6
|
684
|
+
def types
|
685
|
+
@types ||= list_types.to_a.each do |type|
|
686
|
+
type.instance_variable_set(:@is_standalone, false)
|
687
|
+
end
|
688
|
+
end
|
689
|
+
end
|
650
690
|
end
|
651
691
|
|
652
692
|
# Information about types
|
@@ -851,6 +891,15 @@ class OCI8
|
|
851
891
|
attr_get_string(OCI_ATTR_SUPERTYPE_NAME) if is_subtype?
|
852
892
|
end
|
853
893
|
|
894
|
+
# Returns the package name if the type is a package type.
|
895
|
+
# Otherwise, +nil+.
|
896
|
+
#
|
897
|
+
# @return [String or nil]
|
898
|
+
# @since 2.1.6
|
899
|
+
def package_name
|
900
|
+
attr_get_string(12, false) # OCI_ATTR_PACKAGE_NAME
|
901
|
+
end
|
902
|
+
|
854
903
|
# Returns attribute information of the type.
|
855
904
|
#
|
856
905
|
# @return [array of OCI8::Metadata::TypeAttr]
|
@@ -1199,6 +1248,7 @@ class OCI8
|
|
1199
1248
|
# schema name of the synonym translation
|
1200
1249
|
def schema_name
|
1201
1250
|
@schema_name ||= attr_get_string(OCI_ATTR_SCHEMA_NAME)
|
1251
|
+
@schema_name.size == 0 ? nil : @schema_name
|
1202
1252
|
end
|
1203
1253
|
|
1204
1254
|
# object name of the synonym translation
|
@@ -1214,11 +1264,7 @@ class OCI8
|
|
1214
1264
|
|
1215
1265
|
# full-qualified synonym translation name with schema, object and database link name.
|
1216
1266
|
def translated_name
|
1217
|
-
|
1218
|
-
schema_name + '.' + name
|
1219
|
-
else
|
1220
|
-
schema_name + '.' + name + '@' + link
|
1221
|
-
end
|
1267
|
+
(schema_name ? schema_name + '.' : '') + name + (link ? '@' + link : '')
|
1222
1268
|
end
|
1223
1269
|
|
1224
1270
|
def inspect # :nodoc:
|
@@ -1487,10 +1533,21 @@ class OCI8
|
|
1487
1533
|
end
|
1488
1534
|
|
1489
1535
|
# Indicates whether an argument has a default
|
1536
|
+
#
|
1537
|
+
# @return [1 or 0]
|
1538
|
+
# @deprecated
|
1490
1539
|
def has_default
|
1491
1540
|
attr_get_ub1(OCI_ATTR_HAS_DEFAULT)
|
1492
1541
|
end
|
1493
1542
|
|
1543
|
+
# Indicates whether an argument has a default
|
1544
|
+
#
|
1545
|
+
# @return [true or false]
|
1546
|
+
# @since 2.1.6
|
1547
|
+
def has_default?
|
1548
|
+
__boolean(OCI_ATTR_HAS_DEFAULT)
|
1549
|
+
end
|
1550
|
+
|
1494
1551
|
# The list of arguments at the next level (when the argument is
|
1495
1552
|
# of a record or table type).
|
1496
1553
|
def list_arguments
|
@@ -1648,8 +1705,9 @@ class OCI8
|
|
1648
1705
|
#when OCI_LTYPE_TABLE_ALIAS; offset = ?
|
1649
1706
|
#when OCI_LTYPE_VARIABLE_TYPE; offset = ?
|
1650
1707
|
#when OCI_LTYPE_NAME_VALUE; offset = ?
|
1708
|
+
when 15; offset = 0 # OCI_LTYPE_PACKAGE_TYPE
|
1651
1709
|
else
|
1652
|
-
raise NotImplementedError, "unsupported list type #{
|
1710
|
+
raise NotImplementedError, "unsupported list type #{ltype}"
|
1653
1711
|
end
|
1654
1712
|
ary = []
|
1655
1713
|
0.upto(num_params - 1) do |i|
|
@@ -1994,7 +2052,13 @@ class OCI8
|
|
1994
2052
|
# @param [String] object_name
|
1995
2053
|
# @return [a subclass of OCI8::Metadata::Base]
|
1996
2054
|
def describe_any(object_name)
|
1997
|
-
|
2055
|
+
if /^PUBLIC\.(.*)/i =~ object_name
|
2056
|
+
md = __describe($1, OCI8::Metadata::Unknown, true)
|
2057
|
+
raise OCIError.new(4043, object_name) if md.obj_schema != 'PUBLIC'
|
2058
|
+
md
|
2059
|
+
else
|
2060
|
+
__describe(object_name, OCI8::Metadata::Unknown, true)
|
2061
|
+
end
|
1998
2062
|
end
|
1999
2063
|
# Returns table or view information. If the name is a current schema's synonym
|
2000
2064
|
# name or a public synonym name, it returns table or view information which
|
@@ -2011,6 +2075,9 @@ class OCI8
|
|
2011
2075
|
__describe(table_name, OCI8::Metadata::Table, false)
|
2012
2076
|
else
|
2013
2077
|
# check tables, views, synonyms and public synonyms.
|
2078
|
+
|
2079
|
+
# follow synonyms up to 20 times to prevent infinite loop
|
2080
|
+
# caused by recursive synonyms.
|
2014
2081
|
recursive_level = 20
|
2015
2082
|
recursive_level.times do
|
2016
2083
|
metadata = __describe(table_name, OCI8::Metadata::Unknown, true)
|
@@ -2019,6 +2086,11 @@ class OCI8
|
|
2019
2086
|
return metadata
|
2020
2087
|
when OCI8::Metadata::Synonym
|
2021
2088
|
table_name = metadata.translated_name
|
2089
|
+
if metadata.obj_link and metadata.link.nil?
|
2090
|
+
# table_name is a synonym in a remote database for an object in the
|
2091
|
+
# remote database itself.
|
2092
|
+
table_name = "#{table_name}@#{metadata.obj_link}"
|
2093
|
+
end
|
2022
2094
|
else
|
2023
2095
|
raise OCIError.new(4043, table_name) # ORA-04043: object %s does not exist
|
2024
2096
|
end
|
@@ -2066,7 +2138,13 @@ class OCI8
|
|
2066
2138
|
# @param [String] synonym_name
|
2067
2139
|
# @return [OCI8::Metadata::Synonym]
|
2068
2140
|
def describe_synonym(synonym_name, check_public_also = true)
|
2069
|
-
|
2141
|
+
if /^PUBLIC\.(.*)/i =~ synonym_name
|
2142
|
+
md = __describe($1, OCI8::Metadata::Synonym, true)
|
2143
|
+
raise OCIError.new(4043, synonym_name) if md.obj_schema != 'PUBLIC'
|
2144
|
+
md
|
2145
|
+
else
|
2146
|
+
__describe(synonym_name, OCI8::Metadata::Synonym, check_public_also)
|
2147
|
+
end
|
2070
2148
|
end
|
2071
2149
|
# Returns sequence information
|
2072
2150
|
#
|
data/lib/oci8/object.rb
CHANGED
@@ -71,6 +71,29 @@ EOS
|
|
71
71
|
OCI8::TDO.new(self, metadata, klass)
|
72
72
|
end
|
73
73
|
|
74
|
+
# Returns the type descriptor object which correspond to the given type name.
|
75
|
+
#
|
76
|
+
# @param [String] typename
|
77
|
+
# @return [OCI8::TDO]
|
78
|
+
#
|
79
|
+
# @private
|
80
|
+
def get_tdo_by_typename(typename)
|
81
|
+
tdo = @name_to_tdo && @name_to_tdo[typename]
|
82
|
+
return tdo if tdo
|
83
|
+
|
84
|
+
metadata = describe_any(typename)
|
85
|
+
if metadata.is_a? OCI8::Metadata::Synonym
|
86
|
+
metadata = describe_any(metadata.translated_name)
|
87
|
+
end
|
88
|
+
unless metadata.is_a? OCI8::Metadata::Type
|
89
|
+
raise "unknown typename #{typename}"
|
90
|
+
end
|
91
|
+
tdo = get_tdo_by_metadata(metadata)
|
92
|
+
|
93
|
+
@name_to_tdo[typename] = tdo
|
94
|
+
tdo
|
95
|
+
end
|
96
|
+
|
74
97
|
# A helper class to bind arguments.
|
75
98
|
#
|
76
99
|
# @private
|
data/lib/oci8lib_200.so
CHANGED
Binary file
|
data/lib/oci8lib_210.so
ADDED
Binary file
|
data/ruby-oci8.gemspec
CHANGED
@@ -19,7 +19,7 @@ spec = Gem::Specification.new do |s|
|
|
19
19
|
s.version = File.read('VERSION').strip
|
20
20
|
s.summary = 'Ruby interface for Oracle using OCI8 API'
|
21
21
|
s.email = 'kubo@jiubao.org'
|
22
|
-
s.homepage = '
|
22
|
+
s.homepage = 'https://github.com/kubo/ruby-oci8/'
|
23
23
|
s.rubyforge_project = 'ruby-oci8'
|
24
24
|
s.description = <<EOS
|
25
25
|
ruby-oci8 is a ruby interface for Oracle using OCI8 API. It is available with Oracle8i, Oracle9i, Oracle10g, Oracle11g and Oracle Instant Client.
|
data/test/config.rb
CHANGED
@@ -18,6 +18,21 @@ $lobreadnum = 256 # counts in charactors
|
|
18
18
|
|
19
19
|
# don't modify below.
|
20
20
|
|
21
|
+
begin
|
22
|
+
require 'minitest/autorun'
|
23
|
+
Minitest = MiniTest unless defined? Minitest
|
24
|
+
Minitest::Test = Minitest::Unit::TestCase unless defined? Minitest::Test
|
25
|
+
rescue LoadError
|
26
|
+
require 'test/unit'
|
27
|
+
module Minitest
|
28
|
+
Test = ::Test::Unit::TestCase
|
29
|
+
Assertions = ::Test::Unit::Assertions
|
30
|
+
module Assertions
|
31
|
+
alias refute_nil assert_not_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
21
36
|
# $oracle_server_version: database compatible level of the Oracle server.
|
22
37
|
# $oracle_client_version: Oracle client library version for which oci8 is compiled.
|
23
38
|
# $oracle_version: lower value of $oracle_server_version and $oracle_client_version.
|
@@ -108,77 +123,72 @@ def convert_to_datetime(year, month, day, hour, minute, sec, subsec, timezone)
|
|
108
123
|
end
|
109
124
|
end
|
110
125
|
|
111
|
-
|
112
|
-
module Unit
|
113
|
-
class TestCase
|
126
|
+
class Minitest::Test
|
114
127
|
|
115
|
-
|
116
|
-
|
128
|
+
def get_oci8_connection()
|
129
|
+
OCI8.new($dbuser, $dbpass, $dbname)
|
117
130
|
rescue OCIError
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
131
|
+
raise if $!.code != 12516 && $!.code != 12520
|
132
|
+
# sleep a few second and try again if
|
133
|
+
# the error code is ORA-12516 or ORA-12520.
|
134
|
+
#
|
135
|
+
# ORA-12516 - TNS:listener could not find available handler with
|
136
|
+
# matching protocol stack
|
137
|
+
# ORA-12520 - TNS:listener could not find available handler for
|
138
|
+
# requested type of server
|
139
|
+
#
|
140
|
+
# Thanks to Christopher Jones.
|
141
|
+
#
|
142
|
+
# Ref: The Underground PHP and Oracle Manual (page 175 in vesion 1.4)
|
143
|
+
# http://www.oracle.com/technology/tech/php/pdf/underground-php-oracle-manual.pdf
|
144
|
+
#
|
145
|
+
sleep(5)
|
146
|
+
OCI8.new($dbuser, $dbpass, $dbname)
|
147
|
+
end
|
148
|
+
|
149
|
+
def get_dbi_connection()
|
150
|
+
DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
|
151
|
+
rescue DBI::DatabaseError
|
152
|
+
raise if $!.err != 12516 && $!.err != 12520
|
153
|
+
# same as get_oci8_connection()
|
154
|
+
sleep(5)
|
155
|
+
DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
|
156
|
+
end
|
135
157
|
|
136
|
-
|
137
|
-
|
158
|
+
def drop_table(table_name)
|
159
|
+
if $oracle_server_version < OCI8::ORAVER_10_1
|
160
|
+
# Oracle 8 - 9i
|
161
|
+
sql = "DROP TABLE #{table_name}"
|
162
|
+
else
|
163
|
+
# Oracle 10g -
|
164
|
+
sql = "DROP TABLE #{table_name} PURGE"
|
165
|
+
end
|
166
|
+
|
167
|
+
if defined? @conn
|
168
|
+
begin
|
169
|
+
@conn.exec(sql)
|
170
|
+
rescue OCIError
|
171
|
+
raise if $!.code != 942 # table or view does not exist
|
172
|
+
end
|
173
|
+
elsif instance_variable_get(:@dbh)
|
174
|
+
begin
|
175
|
+
@dbh.do(sql)
|
138
176
|
rescue DBI::DatabaseError
|
139
|
-
raise if $!.err !=
|
140
|
-
# same as get_oci8_connection()
|
141
|
-
sleep(5)
|
142
|
-
DBI.connect("dbi:OCI8:#{$dbname}", $dbuser, $dbpass, 'AutoCommit' => false)
|
177
|
+
raise if $!.err != 942 # table or view does not exist
|
143
178
|
end
|
179
|
+
end
|
180
|
+
end # drop_table
|
144
181
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
# Oracle 10g -
|
151
|
-
sql = "DROP TABLE #{table_name} PURGE"
|
152
|
-
end
|
153
|
-
|
154
|
-
if defined? @conn
|
155
|
-
begin
|
156
|
-
@conn.exec(sql)
|
157
|
-
rescue OCIError
|
158
|
-
raise if $!.code != 942 # table or view does not exist
|
159
|
-
end
|
160
|
-
elsif instance_variable_get(:@dbh)
|
161
|
-
begin
|
162
|
-
@dbh.do(sql)
|
163
|
-
rescue DBI::DatabaseError
|
164
|
-
raise if $!.err != 942 # table or view does not exist
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end # drop_table
|
168
|
-
|
169
|
-
def drop_type(type_name)
|
170
|
-
begin
|
171
|
-
@conn.exec("DROP TYPE BODY #{type_name}")
|
172
|
-
rescue OCIError
|
173
|
-
raise if $!.code != 4043
|
174
|
-
end
|
175
|
-
begin
|
176
|
-
@conn.exec("DROP TYPE #{type_name}")
|
177
|
-
rescue OCIError
|
178
|
-
raise if $!.code != 4043
|
179
|
-
end
|
180
|
-
end # drop_type
|
182
|
+
def drop_type(type_name)
|
183
|
+
begin
|
184
|
+
@conn.exec("DROP TYPE BODY #{type_name}")
|
185
|
+
rescue OCIError
|
186
|
+
raise if $!.code != 4043
|
181
187
|
end
|
182
|
-
|
188
|
+
begin
|
189
|
+
@conn.exec("DROP TYPE #{type_name}")
|
190
|
+
rescue OCIError
|
191
|
+
raise if $!.code != 4043
|
192
|
+
end
|
193
|
+
end # drop_type
|
183
194
|
end
|
184
|
-
|
data/test/test_all.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
srcdir = File.dirname(__FILE__)
|
2
2
|
|
3
3
|
require 'oci8'
|
4
|
-
require 'test/unit'
|
5
4
|
require "#{srcdir}/config"
|
6
5
|
|
7
6
|
require "#{srcdir}/test_oradate"
|
@@ -30,6 +29,10 @@ if OCI8.respond_to? :encoding
|
|
30
29
|
require "#{srcdir}/test_encoding"
|
31
30
|
end
|
32
31
|
|
32
|
+
if $oracle_version >= OCI8::ORAVER_12_1
|
33
|
+
require "#{srcdir}/test_package_type"
|
34
|
+
end
|
35
|
+
|
33
36
|
# Ruby/DBI
|
34
37
|
begin
|
35
38
|
require 'dbi'
|
@@ -47,8 +50,3 @@ unless dbi_not_found
|
|
47
50
|
require "#{srcdir}/test_dbi_clob"
|
48
51
|
end
|
49
52
|
end
|
50
|
-
|
51
|
-
#Test::Unit::AutoRunner.run(true, true)
|
52
|
-
if defined? Test::Unit::AutoRunner
|
53
|
-
Test::Unit::AutoRunner.run()
|
54
|
-
end
|
data/test/test_appinfo.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
require 'oci8'
|
2
|
-
require 'test/unit'
|
3
2
|
require File.dirname(__FILE__) + '/config'
|
4
3
|
|
5
|
-
class TestAppInfo < Test
|
4
|
+
class TestAppInfo < Minitest::Test
|
6
5
|
|
7
6
|
def setup
|
8
7
|
@conn = get_oci8_connection
|
@@ -14,7 +13,7 @@ class TestAppInfo < Test::Unit::TestCase
|
|
14
13
|
@conn.client_identifier = client_id
|
15
14
|
assert_equal(client_id, @conn.select_one("SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL")[0]);
|
16
15
|
# check the first character
|
17
|
-
|
16
|
+
assert_raises ArgumentError do
|
18
17
|
@conn.client_identifier = ':bad_identifier'
|
19
18
|
end
|
20
19
|
|