ruby-oci8 2.0.1 → 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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