ruby-oci8 2.0.1 → 2.0.2

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.
@@ -1,5 +1,12 @@
1
- # --*- ruby -*--
2
- # This is based on yoshidam's oracle.rb.
1
+ #--
2
+ # oci8.rb -- OCI8 and OCI8::Cursor
3
+ #
4
+ # Copyright (C) 2002-2009 KUBO Takehiro <kubo@jiubao.org>
5
+ #
6
+ # Original Copyright is:
7
+ # Oracle module for Ruby
8
+ # 1998-2000 by yoshidam
9
+ #++
3
10
 
4
11
  require 'date'
5
12
 
@@ -122,6 +129,20 @@ class OCI8
122
129
  end
123
130
  end # exec
124
131
 
132
+ # :call-seq:
133
+ # select_one(sql, *bindvars) -> first_one_row
134
+ #
135
+ def select_one(sql, *bindvars)
136
+ cursor = self.parse(sql)
137
+ begin
138
+ cursor.exec(*bindvars)
139
+ row = cursor.fetch
140
+ ensure
141
+ cursor.close
142
+ end
143
+ return row
144
+ end
145
+
125
146
  def username
126
147
  @username || begin
127
148
  exec('select user from dual') do |row|
@@ -160,133 +181,6 @@ class OCI8
160
181
  @oracle_server_version
161
182
  end
162
183
 
163
- module BindType
164
- Mapping = {}
165
-
166
- class Base
167
- def self.create(con, val, param, max_array_size)
168
- self.new(con, val, param, max_array_size)
169
- end
170
- end
171
-
172
- # get/set Date
173
- class Date < OCI8::BindType::OraDate
174
- def set(val)
175
- super(val && ::OraDate.new(val.year, val.mon, val.mday))
176
- end
177
- def get()
178
- (val = super()) && val.to_date
179
- end
180
- end
181
-
182
- # get/set Number (for OCI8::SQLT_NUM)
183
- class Number
184
- def self.create(con, val, param, max_array_size)
185
- if param.is_a? OCI8::Metadata::Base
186
- precision = param.precision
187
- scale = param.scale
188
- end
189
- if scale == -127
190
- if precision == 0
191
- # NUMBER declared without its scale and precision. (Oracle 9.2.0.3 or above)
192
- klass = OCI8::BindType::Mapping[:number_no_prec_setting]
193
- else
194
- # FLOAT or FLOAT(p)
195
- klass = OCI8::BindType::Float
196
- end
197
- elsif scale == 0
198
- if precision == 0
199
- # NUMBER whose scale and precision is unknown
200
- # or
201
- # NUMBER declared without its scale and precision. (Oracle 9.2.0.2 or below)
202
- klass = OCI8::BindType::Mapping[:number_unknown_prec]
203
- else
204
- # NUMBER(p, 0)
205
- klass = OCI8::BindType::Integer
206
- end
207
- else
208
- # NUMBER(p, s)
209
- if precision < 15 # the precision of double.
210
- klass = OCI8::BindType::Float
211
- else
212
- # use BigDecimal instead?
213
- klass = OCI8::BindType::OraNumber
214
- end
215
- end
216
- klass.new(con, val, nil, max_array_size)
217
- end
218
- end
219
-
220
- class String
221
- def self.create(con, val, param, max_array_size)
222
- case param
223
- when Hash
224
- # 1333 = ceil(4000 (max size of char) / 3 (NLS ratio of UTF8))
225
- length = 1333 # default length
226
- if param[:length]
227
- length = param[:length]
228
- elsif val.respond_to? :to_str and val.to_str.size > length
229
- length = val.to_str.size
230
- end
231
- when OCI8::Metadata::Base
232
- case param.data_type
233
- when :char, :varchar2
234
- length = param.data_size
235
- # character size may become large on character set conversion.
236
- # The length of a Japanese half-width kana is one in Shift_JIS,
237
- # two in EUC-JP, three in UTF-8.
238
- length *= 3 unless param.char_used?
239
- when :raw
240
- # HEX needs twice space.
241
- length = param.data_size * 2
242
- else
243
- length = 100
244
- end
245
- end
246
- self.new(con, val, length, max_array_size)
247
- end
248
- end
249
-
250
- class RAW
251
- def self.create(con, val, param, max_array_size)
252
- case param
253
- when Hash
254
- length = 400 # default length
255
- if param[:length]
256
- length = param[:length]
257
- elsif val.respond_to? :to_str and val.to_str.size > length
258
- length = val.to_str.size
259
- end
260
- when OCI8::Metadata::Base
261
- length = param.data_size
262
- end
263
- self.new(con, val, length, max_array_size)
264
- end
265
- end
266
-
267
- class Long < OCI8::BindType::String
268
- def self.create(con, val, param, max_array_size)
269
- self.new(con, val, con.long_read_len, max_array_size)
270
- end
271
- end
272
-
273
- class LongRaw < OCI8::BindType::RAW
274
- def self.create(con, val, param, max_array_size)
275
- self.new(con, val, con.long_read_len, max_array_size)
276
- end
277
- end
278
-
279
- class CLOB
280
- def self.create(con, val, param, max_array_size)
281
- if param.is_a? OCI8::Metadata::Base and param.charset_form == :nchar
282
- OCI8::BindType::NCLOB.new(con, val, nil, max_array_size)
283
- else
284
- OCI8::BindType::CLOB.new(con, val, nil, max_array_size)
285
- end
286
- end
287
- end
288
- end # BindType
289
-
290
184
  # The instance of this class corresponds to cursor in the term of
291
185
  # Oracle, which corresponds to java.sql.Statement of JDBC and statement
292
186
  # handle $sth of Perl/DBI.
@@ -655,144 +549,3 @@ class String
655
549
  OraNumber.new(self, format, nls_params)
656
550
  end
657
551
  end
658
-
659
- # bind or explicitly define
660
- OCI8::BindType::Mapping[String] = OCI8::BindType::String
661
- OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber
662
- OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer
663
- OCI8::BindType::Mapping[Float] = OCI8::BindType::Float
664
- OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer
665
- OCI8::BindType::Mapping[Bignum] = OCI8::BindType::Integer
666
- OCI8::BindType::Mapping[OraDate] = OCI8::BindType::OraDate
667
- OCI8::BindType::Mapping[Time] = OCI8::BindType::Time
668
- OCI8::BindType::Mapping[Date] = OCI8::BindType::Date
669
- OCI8::BindType::Mapping[DateTime] = OCI8::BindType::DateTime
670
- OCI8::BindType::Mapping[OCI8::CLOB] = OCI8::BindType::CLOB
671
- OCI8::BindType::Mapping[OCI8::NCLOB] = OCI8::BindType::NCLOB
672
- OCI8::BindType::Mapping[OCI8::BLOB] = OCI8::BindType::BLOB
673
- OCI8::BindType::Mapping[OCI8::BFILE] = OCI8::BindType::BFILE
674
- OCI8::BindType::Mapping[OCI8::Cursor] = OCI8::BindType::Cursor
675
-
676
- # implicitly define
677
-
678
- # datatype type size prec scale
679
- # -------------------------------------------------
680
- # CHAR(1) SQLT_AFC 1 0 0
681
- # CHAR(10) SQLT_AFC 10 0 0
682
- OCI8::BindType::Mapping[:char] = OCI8::BindType::String
683
-
684
- # datatype type size prec scale
685
- # -------------------------------------------------
686
- # VARCHAR(1) SQLT_CHR 1 0 0
687
- # VARCHAR(10) SQLT_CHR 10 0 0
688
- # VARCHAR2(1) SQLT_CHR 1 0 0
689
- # VARCHAR2(10) SQLT_CHR 10 0 0
690
- OCI8::BindType::Mapping[:varchar2] = OCI8::BindType::String
691
-
692
- # datatype type size prec scale
693
- # -------------------------------------------------
694
- # RAW(1) SQLT_BIN 1 0 0
695
- # RAW(10) SQLT_BIN 10 0 0
696
- OCI8::BindType::Mapping[:raw] = OCI8::BindType::RAW
697
-
698
- # datatype type size prec scale
699
- # -------------------------------------------------
700
- # LONG SQLT_LNG 0 0 0
701
- OCI8::BindType::Mapping[:long] = OCI8::BindType::Long
702
-
703
- # datatype type size prec scale
704
- # -------------------------------------------------
705
- # LONG RAW SQLT_LBI 0 0 0
706
- OCI8::BindType::Mapping[:long_raw] = OCI8::BindType::LongRaw
707
-
708
- # datatype type size prec scale
709
- # -------------------------------------------------
710
- # CLOB SQLT_CLOB 4000 0 0
711
- OCI8::BindType::Mapping[:clob] = OCI8::BindType::CLOB
712
- OCI8::BindType::Mapping[:nclob] = OCI8::BindType::NCLOB
713
-
714
- # datatype type size prec scale
715
- # -------------------------------------------------
716
- # BLOB SQLT_BLOB 4000 0 0
717
- OCI8::BindType::Mapping[:blob] = OCI8::BindType::BLOB
718
-
719
- # datatype type size prec scale
720
- # -------------------------------------------------
721
- # BFILE SQLT_BFILE 4000 0 0
722
- OCI8::BindType::Mapping[:bfile] = OCI8::BindType::BFILE
723
-
724
- # datatype type size prec scale
725
- # -------------------------------------------------
726
- # DATE SQLT_DAT 7 0 0
727
- OCI8::BindType::Mapping[:date] = OCI8::BindType::Time
728
-
729
- if OCI8.oracle_client_version >= OCI8::ORAVER_9_0
730
- OCI8::BindType::Mapping[:timestamp] = OCI8::BindType::Time
731
- OCI8::BindType::Mapping[:timestamp_tz] = OCI8::BindType::Time
732
- OCI8::BindType::Mapping[:timestamp_ltz] = OCI8::BindType::Time
733
- OCI8::BindType::Mapping[:interval_ym] = OCI8::BindType::IntervalYM
734
- OCI8::BindType::Mapping[:interval_ds] = OCI8::BindType::IntervalDS
735
- end
736
-
737
- # datatype type size prec scale
738
- # -------------------------------------------------
739
- # ROWID SQLT_RDD 4 0 0
740
- OCI8::BindType::Mapping[:rowid] = OCI8::BindType::String
741
-
742
- # datatype type size prec scale
743
- # -----------------------------------------------------
744
- # FLOAT SQLT_NUM 22 126 -127
745
- # FLOAT(1) SQLT_NUM 22 1 -127
746
- # FLOAT(126) SQLT_NUM 22 126 -127
747
- # DOUBLE PRECISION SQLT_NUM 22 126 -127
748
- # REAL SQLT_NUM 22 63 -127
749
- # NUMBER SQLT_NUM 22 0 0
750
- # NUMBER(1) SQLT_NUM 22 1 0
751
- # NUMBER(38) SQLT_NUM 22 38 0
752
- # NUMBER(1, 0) SQLT_NUM 22 1 0
753
- # NUMBER(38, 0) SQLT_NUM 22 38 0
754
- # NUMERIC SQLT_NUM 22 38 0
755
- # INT SQLT_NUM 22 38 0
756
- # INTEGER SQLT_NUM 22 38 0
757
- # SMALLINT SQLT_NUM 22 38 0
758
- OCI8::BindType::Mapping[:number] = OCI8::BindType::Number
759
-
760
- # mapping for calculated number values.
761
- #
762
- # for example:
763
- # select col1 * 1.1 from tab1;
764
- #
765
- # For Oracle 9.2.0.2 or below, this is also used for NUMBER
766
- # datatypes that have no explicit setting of their precision
767
- # and scale.
768
- #
769
- # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
770
- # for ruby-oci8 2.0.
771
- OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
772
-
773
- # mapping for number without precision and scale.
774
- #
775
- # for example:
776
- # create table tab1 (col1 number);
777
- # select col1 from tab1;
778
- #
779
- # note: This is available only on Oracle 9.2.0.3 or above.
780
- # see: Oracle 9.2.0.x Patch Set Notes.
781
- #
782
- # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
783
- # for ruby-oci8 2.0.
784
- OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
785
-
786
- if defined? OCI8::BindType::BinaryDouble
787
- OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
788
- OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::BinaryDouble
789
- else
790
- OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::Float
791
- OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::Float
792
- end
793
-
794
- # Cursor
795
- OCI8::BindType::Mapping[:cursor] = OCI8::BindType::Cursor
796
-
797
- # XMLType (This mapping will be changed before release.)
798
- OCI8::BindType::Mapping[:xmltype] = OCI8::BindType::Long
@@ -19,16 +19,25 @@ require "#{srcdir}/test_connstr"
19
19
  require "#{srcdir}/test_metadata"
20
20
  require "#{srcdir}/test_array_dml"
21
21
  require "#{srcdir}/test_rowid"
22
+ require "#{srcdir}/test_appinfo"
22
23
  require "#{srcdir}/test_oracle_version"
23
24
 
25
+ if OCI8.respond_to? :encoding
26
+ require "#{srcdir}/test_encoding"
27
+ end
28
+
24
29
  # Ruby/DBI
25
30
  begin
26
31
  require 'dbi'
27
- is_dbi_loaded = true
28
32
  rescue LoadError
29
- is_dbi_loaded = false
33
+ begin
34
+ require 'rubygems'
35
+ require 'dbi'
36
+ rescue LoadError
37
+ dbi_not_found = true
38
+ end
30
39
  end
31
- if is_dbi_loaded
40
+ unless dbi_not_found
32
41
  require "#{srcdir}/test_dbi"
33
42
  if $test_clob
34
43
  require "#{srcdir}/test_dbi_clob"
@@ -0,0 +1,29 @@
1
+ require 'oci8'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/config'
4
+
5
+ class TestAppInfo < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @conn = get_oci8_connection
9
+ end
10
+
11
+ def test_set_client_identifier
12
+ # set client_id
13
+ client_id = "ruby-oci8:#{Process.pid()}"
14
+ @conn.client_identifier = client_id
15
+ assert_equal(client_id, @conn.select_one("SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL")[0]);
16
+ # check the first character
17
+ assert_raise ArgumentError do
18
+ @conn.client_identifier = ':bad_identifier'
19
+ end
20
+
21
+ # clear client_id
22
+ @conn.client_identifier = nil
23
+ assert_nil(@conn.select_one("SELECT SYS_CONTEXT('USERENV', 'CLIENT_IDENTIFIER') FROM DUAL")[0]);
24
+ end
25
+
26
+ def teardown
27
+ @conn.logoff
28
+ end
29
+ end
@@ -252,7 +252,7 @@ EOS
252
252
 
253
253
  drop_table('test_table')
254
254
  @dbh.execute(<<-EOS)
255
- CREATE TABLE test_table (#{i = 0; coldef.collect do |c| i += 1; "C#{i} " + c[1] + (c[8] ? ' PRIMARY KEY' : ''); end.join(',')})
255
+ CREATE TABLE test_table (#{n = 0; coldef.collect do |c| n += 1; "C#{n} " + c[1] + (c[8] ? ' PRIMARY KEY' : ''); end.join(',')})
256
256
  STORAGE (
257
257
  INITIAL 100k
258
258
  NEXT 100k
@@ -0,0 +1,100 @@
1
+ require 'oci8'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/config'
4
+
5
+ class TestEncoding < Test::Unit::TestCase
6
+ def setup
7
+ @conn = get_oci8_connection
8
+ end
9
+
10
+ def test_select
11
+ drop_table('test_table')
12
+ @conn.exec(<<EOS)
13
+ CREATE TABLE test_table
14
+ (C CHAR(10),
15
+ V VARCHAR2(10),
16
+ R RAW(10),
17
+ LR LONG RAW,
18
+ CL CLOB,
19
+ NCL NCLOB,
20
+ BL BLOB)
21
+ STORAGE (
22
+ INITIAL 4k
23
+ NEXT 4k
24
+ MINEXTENTS 1
25
+ MAXEXTENTS UNLIMITED
26
+ PCTINCREASE 0)
27
+ EOS
28
+ ascii_8bit = Encoding.find('ASCII-8BIT')
29
+ @conn.exec(<<EOS)
30
+ INSERT INTO test_table VALUES ('abcd', 'abcd', 'abcd', 'abcd', 'abcd', 'abcd', 'abcd')
31
+ EOS
32
+ @conn.exec("SELECT * FROM test_table") do |row|
33
+ assert_equal('abcd ', row[0], 'CHAR(10)')
34
+ assert_equal(OCI8.encoding, row[0].encoding);
35
+ assert_equal('abcd', row[1], 'VARCHAR2(10)')
36
+ assert_equal(OCI8.encoding, row[1].encoding);
37
+ assert_equal("\xab\xcd", row[2], 'RAW(10)')
38
+ assert_equal(ascii_8bit, row[2].encoding);
39
+ assert_equal("\xab\xcd", row[3], 'LONG RAW')
40
+ assert_equal(ascii_8bit, row[3].encoding);
41
+ assert_equal('abcd', (data = row[4].read), 'CLOB')
42
+ assert_equal(OCI8.encoding, data.encoding);
43
+ assert_equal('abcd', (data = row[5].read), 'NCLOB')
44
+ assert_equal(OCI8.encoding, data.encoding);
45
+ assert_equal("\xab\xcd", (data = row[6].read), 'BLOB')
46
+ assert_equal(ascii_8bit, data.encoding);
47
+
48
+ if OCI8.encoding.name == "UTF-8"
49
+ utf_8 = "\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7\u00A8\u00A9"
50
+ iso_8859_1 = utf_8.encode("ISO-8859-1")
51
+ # CLOB
52
+ lob = row[4]
53
+ lob.rewind
54
+ lob.write(iso_8859_1) # converted to OCI8.encoding(UTF-8)
55
+ lob.rewind
56
+ assert_equal(utf_8, lob.read)
57
+ # NCLOB
58
+ lob = row[5]
59
+ lob.rewind
60
+ lob.write(iso_8859_1) # converted to OCI8.encoding(UTF-8)
61
+ lob.rewind
62
+ assert_equal(utf_8, lob.read)
63
+ # BLOB
64
+ lob = row[6]
65
+ lob.rewind
66
+ lob.write(iso_8859_1) # written without encoding conversion
67
+ lob.rewind
68
+ assert_equal(iso_8859_1.force_encoding('ASCII-8BIT'), lob.read)
69
+ end
70
+ end
71
+ drop_table('test_table')
72
+ end
73
+
74
+ if OCI8.encoding.name == "UTF-8"
75
+ def test_bind_string_with_code_conversion
76
+ drop_table('test_table')
77
+ @conn.exec(<<EOS)
78
+ CREATE TABLE test_table
79
+ (V VARCHAR2(3000))
80
+ STORAGE (
81
+ INITIAL 4k
82
+ NEXT 4k
83
+ MINEXTENTS 1
84
+ MAXEXTENTS UNLIMITED
85
+ PCTINCREASE 0)
86
+ EOS
87
+ utf_8 = "\u00A1" * 1500 # 3000 byte
88
+ iso_8859_1 = utf_8.encode("ISO-8859-1") # 1500 byte
89
+ @conn.exec("INSERT INTO test_table VALUES (:1)", iso_8859_1)
90
+ @conn.exec("SELECT * FROM test_table") do |row|
91
+ assert_equal(utf_8, row[0])
92
+ end
93
+ drop_table('test_table')
94
+ end
95
+ end
96
+
97
+ def teardown
98
+ @conn.logoff
99
+ end
100
+ end