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.
@@ -48,48 +48,69 @@ module MiniRegistry
48
48
  # copy the minimum code and reorganize it.
49
49
  ERROR_SUCCESS = 0
50
50
  ERROR_FILE_NOT_FOUND = 2
51
+ ERROR_NO_MORE_ITEMS = 259
51
52
 
52
53
  HKEY_LOCAL_MACHINE = 0x80000002
54
+ KEY_ENUMERATE_SUB_KEYS = 0x0008
55
+ KEY_QUERY_VALUE = 0x0001
53
56
  RegOpenKeyExA = Win32API.new('advapi32', 'RegOpenKeyExA', 'LPLLP', 'L')
57
+ RegEnumKeyExA = Win32API.new('advapi32', 'RegEnumKeyExA', 'LLPPPPPP', 'L')
54
58
  RegQueryValueExA = Win32API.new('advapi32','RegQueryValueExA','LPPPPP','L')
55
59
  RegCloseKey = Win32API.new('advapi32', 'RegCloseKey', 'L', 'L')
56
60
 
57
- def get_reg_value(root, subkey, name)
58
- result = [0].pack('L')
59
- code = RegOpenKeyExA.call(root, subkey, 0, 0x20019, result)
61
+ def self.get_str_value(hKey, name)
62
+ lpcbData = [0].pack('L')
63
+ code = RegQueryValueExA.call(hKey, name, nil, nil, nil, lpcbData)
64
+ if code == ERROR_FILE_NOT_FOUND
65
+ return nil
66
+ elsif code != ERROR_SUCCESS
67
+ raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
68
+ end
69
+ len = lpcbData.unpack('L')[0]
70
+ lpType = [0].pack('L')
71
+ lpData = "\0"*len
72
+ lpcbData = [len].pack('L')
73
+ code = RegQueryValueExA.call(hKey, name, nil, lpType, lpData, lpcbData)
74
+ if code != ERROR_SUCCESS
75
+ raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
76
+ end
77
+ lpData.unpack('Z*')[0]
78
+ end
79
+
80
+ def self.enum_homes
81
+ phkResult = [0].pack('L')
82
+ code = RegOpenKeyExA.call(HKEY_LOCAL_MACHINE, 'SOFTWARE\ORACLE', 0, 0x20019, phkResult)
60
83
  if code != ERROR_SUCCESS
61
84
  raise MiniRegistryError.new("Win32::RegOpenKeyExA", code)
62
85
  end
63
- hkey = result.unpack('L')[0]
64
- begin
65
- lpcbData = [0].pack('L')
66
- code = RegQueryValueExA.call(hkey, name, nil, nil, nil, lpcbData)
67
- if code == ERROR_FILE_NOT_FOUND
68
- return nil
69
- elsif code != ERROR_SUCCESS
70
- raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
86
+ hKey = phkResult.unpack('L')[0]
87
+ idx = 0
88
+ maxkeylen = 256
89
+ loop do
90
+ lpName = "\0" * maxkeylen
91
+ lpcName = [maxkeylen].pack('L')
92
+ code = RegEnumKeyExA.call(hKey, idx, lpName, lpcName, nil, nil, nil, nil);
93
+ break if code == ERROR_NO_MORE_ITEMS
94
+ if code != ERROR_SUCCESS
95
+ RegCloseKey.call(hKey)
96
+ raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
71
97
  end
72
- len = lpcbData.unpack('L')[0]
73
- lpType = "\0\0\0\0"
74
- lpData = "\0"*len
75
- lpcbData = [len].pack('L')
76
- code = RegQueryValueExA.call(hkey, name, nil, lpType, lpData, lpcbData)
98
+ code = RegOpenKeyExA.call(hKey, lpName, 0, KEY_QUERY_VALUE, phkResult)
77
99
  if code != ERROR_SUCCESS
78
- raise MiniRegistryError.new("Win32::RegQueryValueExA",code)
100
+ RegCloseKey.call(hKey)
101
+ raise MiniRegistryError.new("Win32::RegEnumKeyEx", code)
79
102
  end
80
- lpData.unpack('Z*')[0]
81
- ensure
82
- RegCloseKey.call(hkey)
103
+ hSubkey = phkResult.unpack('L')[0]
104
+
105
+ name = get_str_value(hSubkey, 'ORACLE_HOME_NAME')
106
+ path = get_str_value(hSubkey, 'ORACLE_HOME')
107
+ yield name, path
108
+ RegCloseKey.call(hSubkey)
109
+ idx += 1
83
110
  end
111
+ RegCloseKey.call(hKey)
84
112
  end
85
- def get_local_registry(subkey, name)
86
- get_reg_value(HKEY_LOCAL_MACHINE, subkey, name)
87
- end
88
- else
89
- # UNIX
90
- def get_local_registry(subkey, name)
91
- nil
92
- end
113
+
93
114
  end
94
115
  end # module MiniRegistry
95
116
 
@@ -293,8 +314,6 @@ class MiniSOReader
293
314
  end
294
315
 
295
316
  class OraConf
296
- include MiniRegistry
297
-
298
317
  attr_reader :cc_is_gcc
299
318
  attr_reader :version
300
319
  attr_reader :cflags
@@ -756,26 +775,10 @@ class OraConfFC < OraConf
756
775
  if oracle_home.nil?
757
776
  struct = Struct.new("OracleHome", :name, :path)
758
777
  oracle_homes = []
759
- begin
760
- last_home = get_local_registry("SOFTWARE\\ORACLE\\ALL_HOMES", 'LAST_HOME')
761
- 0.upto last_home.to_i do |id|
762
- oracle_homes << "HOME#{id}"
763
- end
764
- rescue MiniRegistryError
765
- end
766
- oracle_homes << "KEY_XE"
767
- oracle_homes << "KEY_XEClient"
768
- oracle_homes.collect! do |home|
769
- begin
770
- name = get_local_registry("SOFTWARE\\ORACLE\\#{home}", 'ORACLE_HOME_NAME')
771
- path = get_local_registry("SOFTWARE\\ORACLE\\#{home}", 'ORACLE_HOME')
772
- path.chomp!("\\")
773
- struct.new(name, path) if is_valid_home?(path)
774
- rescue MiniRegistryError
775
- nil
776
- end
778
+ MiniRegistry.enum_homes do |name, path|
779
+ path.chomp!("\\") if path
780
+ oracle_homes << struct.new(name, path) if is_valid_home?(path)
777
781
  end
778
- oracle_homes.compact!
779
782
  if oracle_homes.empty?
780
783
  raise <<EOS
781
784
  Set the environment variable ORACLE_HOME if Oracle Full Client.
@@ -945,21 +948,18 @@ EOS
945
948
  end
946
949
  end
947
950
 
948
- # remove object files from libs.
949
- objs = []
950
- libs.gsub!(/\S+\.o\b/) do |obj|
951
- objs << obj
952
- ""
953
- end
954
- # change object files to an archive file to work around.
955
- if objs.length > 0
956
- Logging::open do
957
- puts "change object files to an archive file."
958
- command = Config::CONFIG["AR"] + " cru oracle_objs.a " + objs.join(" ")
959
- puts command
960
- system(command)
961
- libs = "oracle_objs.a " + libs
951
+ # check whether object files are included.
952
+ if /\S+\.o\b/ =~ libs
953
+
954
+ # monkey patching!
955
+ Object.module_eval do
956
+ alias :orig_link_command :link_command
957
+ def link_command(ldflags, opt="", libpath=$DEFLIBPATH|$LIBPATH)
958
+ opt = "" if opt == $libs
959
+ orig_link_command(ldflags, opt, libpath)
960
+ end
962
961
  end
962
+
963
963
  end
964
964
  libs
965
965
  end # get_libs
@@ -3,7 +3,7 @@
3
3
  * oradate.c
4
4
  *
5
5
  * $Author: kubo $
6
- * $Date: 2009-01-04 01:58:01 +0900 (Sun, 04 Jan 2009) $
6
+ * $Date: 2009-05-17 22:07:16 +0900 (Sun, 17 May 2009) $
7
7
  *
8
8
  * Copyright (C) 2002-2008 KUBO Takehiro <kubo@jiubao.org>
9
9
  *
@@ -402,6 +402,21 @@ class Statement < DBI::BaseStatement
402
402
  end
403
403
  end
404
404
 
405
+ # DBI_STMT_NEW_ARGS is DBI::StatementHandle.new's arguments except +handle+.
406
+ #
407
+ # FYI: DBI::StatementHandle.new method signatures are follows:
408
+ # 0.2.2: handle, fetchable=false, prepared=true
409
+ # 0.4.0: handle, fetchable=false, prepared=true, convert_types=true
410
+ # 0.4.1: handle, fetchable=false, prepared=true, convert_types=true, executed=false
411
+ begin
412
+ DBI::StatementHandle.new(nil, false, true, true, true)
413
+ # dbi 0.4.1
414
+ DBI_STMT_NEW_ARGS = [true, true, true, true] # :nodoc:
415
+ rescue ArgumentError
416
+ # dbi 0.4.0 or lower
417
+ DBI_STMT_NEW_ARGS = [true] # :nodoc:
418
+ end
419
+
405
420
  if defined? ::OCI8::BindType::Base
406
421
  ##
407
422
  ## ruby-oci8 2.0 bind classes.
@@ -491,7 +506,7 @@ if defined? ::OCI8::BindType::Base
491
506
  val = super
492
507
  return nil if val.nil?
493
508
  stmt = DBI::DBD::OCI8::Statement.new(val)
494
- DBI::StatementHandle.new(stmt, true, false)
509
+ DBI::StatementHandle.new(stmt, *DBI_STMT_NEW_ARGS)
495
510
  end
496
511
  end
497
512
  end # BindType
@@ -560,7 +575,7 @@ else
560
575
  return val if val.nil?
561
576
  cur = ::OCI8::Cursor.new(@env, @svc, @ctx, val)
562
577
  stmt = DBI::DBD::OCI8::Statement.new(cur)
563
- DBI::StatementHandle.new(stmt, true, false)
578
+ DBI::StatementHandle.new(stmt, *DBI_STMT_NEW_ARGS)
564
579
  end
565
580
  end
566
581
  end
@@ -71,6 +71,7 @@ end
71
71
 
72
72
  require 'oci8/datetime.rb'
73
73
  require 'oci8/oci8.rb'
74
+ require 'oci8/bindtype.rb'
74
75
  require 'oci8/metadata.rb'
75
76
  require 'oci8/compat.rb'
76
77
  require 'oci8/object.rb'
@@ -0,0 +1,295 @@
1
+ #--
2
+ # bindtype.rb -- OCI8::BindType
3
+ #
4
+ # Copyright (C) 2009 KUBO Takehiro <kubo@jiubao.org>
5
+ #++
6
+
7
+ class OCI8
8
+ module BindType
9
+ Mapping = {}
10
+
11
+ class Base
12
+ def self.create(con, val, param, max_array_size)
13
+ self.new(con, val, param, max_array_size)
14
+ end
15
+ end
16
+
17
+ # get/set Date
18
+ class Date < OCI8::BindType::OraDate
19
+ def set(val)
20
+ super(val && ::OraDate.new(val.year, val.mon, val.mday))
21
+ end
22
+ def get()
23
+ (val = super()) && val.to_date
24
+ end
25
+ end
26
+
27
+ # get/set Number (for OCI8::SQLT_NUM)
28
+ class Number
29
+ def self.create(con, val, param, max_array_size)
30
+ if param.is_a? OCI8::Metadata::Base
31
+ precision = param.precision
32
+ scale = param.scale
33
+ end
34
+ if scale == -127
35
+ if precision == 0
36
+ # NUMBER declared without its scale and precision. (Oracle 9.2.0.3 or above)
37
+ klass = OCI8::BindType::Mapping[:number_no_prec_setting]
38
+ else
39
+ # FLOAT or FLOAT(p)
40
+ klass = OCI8::BindType::Float
41
+ end
42
+ elsif scale == 0
43
+ if precision == 0
44
+ # NUMBER whose scale and precision is unknown
45
+ # or
46
+ # NUMBER declared without its scale and precision. (Oracle 9.2.0.2 or below)
47
+ klass = OCI8::BindType::Mapping[:number_unknown_prec]
48
+ else
49
+ # NUMBER(p, 0)
50
+ klass = OCI8::BindType::Integer
51
+ end
52
+ else
53
+ # NUMBER(p, s)
54
+ if precision < 15 # the precision of double.
55
+ klass = OCI8::BindType::Float
56
+ else
57
+ # use BigDecimal instead?
58
+ klass = OCI8::BindType::OraNumber
59
+ end
60
+ end
61
+ klass.new(con, val, nil, max_array_size)
62
+ end
63
+ end
64
+
65
+ class String
66
+ # 1333 <= ceil(4000 / 3). 4000 is max size of char. 3 is NLS ratio of UTF-8.
67
+ @@minimum_bind_length = 1333
68
+
69
+ def self.minimum_bind_length
70
+ @@minimum_bind_length
71
+ end
72
+
73
+ def self.minimum_bind_length=(val)
74
+ @@minimum_bind_length = val
75
+ end
76
+
77
+ def self.create(con, val, param, max_array_size)
78
+ case param
79
+ when Hash
80
+ if param[:length]
81
+ # If length is passed explicitly, use it.
82
+ length = param[:length]
83
+ elsif val.is_a? String or (val.respond_to? :to_str and val = val.to_str)
84
+ if OCI8.respond_to? :encoding and OCI8.encoding != val.encoding
85
+ # If the string encoding is different with NLS_LANG character set,
86
+ # convert it to get the length.
87
+ val = val.encode(OCI8.encoding)
88
+ end
89
+ if val.respond_to? :bytesize
90
+ # ruby 1.8.7 or upper
91
+ length = val.bytesize
92
+ else
93
+ # ruby 1.8.6 or lower
94
+ length = val.size
95
+ end
96
+ end
97
+ when OCI8::Metadata::Base
98
+ case param.data_type
99
+ when :char, :varchar2
100
+ length = param.data_size
101
+ # character size may become large on character set conversion.
102
+ # The length of a Japanese half-width kana is one in Shift_JIS,
103
+ # two in EUC-JP, three in UTF-8.
104
+ length *= 3 unless param.char_used?
105
+ when :raw
106
+ # HEX needs twice space.
107
+ length = param.data_size * 2
108
+ end
109
+ end
110
+ length = @@minimum_bind_length if length.nil? or length < @@minimum_bind_length
111
+ self.new(con, val, length, max_array_size)
112
+ end
113
+ end
114
+
115
+ class RAW
116
+ def self.create(con, val, param, max_array_size)
117
+ case param
118
+ when Hash
119
+ length = 400 # default length
120
+ if param[:length]
121
+ length = param[:length]
122
+ elsif val.respond_to? :to_str and val.to_str.size > length
123
+ length = val.to_str.size
124
+ end
125
+ when OCI8::Metadata::Base
126
+ length = param.data_size
127
+ end
128
+ self.new(con, val, length, max_array_size)
129
+ end
130
+ end
131
+
132
+ class Long < OCI8::BindType::String
133
+ def self.create(con, val, param, max_array_size)
134
+ self.new(con, val, con.long_read_len, max_array_size)
135
+ end
136
+ end
137
+
138
+ class LongRaw < OCI8::BindType::RAW
139
+ def self.create(con, val, param, max_array_size)
140
+ self.new(con, val, con.long_read_len, max_array_size)
141
+ end
142
+ end
143
+
144
+ class CLOB
145
+ def self.create(con, val, param, max_array_size)
146
+ if param.is_a? OCI8::Metadata::Base and param.charset_form == :nchar
147
+ OCI8::BindType::NCLOB.new(con, val, nil, max_array_size)
148
+ else
149
+ OCI8::BindType::CLOB.new(con, val, nil, max_array_size)
150
+ end
151
+ end
152
+ end
153
+ end # BindType
154
+ end
155
+
156
+ # bind or explicitly define
157
+ OCI8::BindType::Mapping[String] = OCI8::BindType::String
158
+ OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber
159
+ OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer
160
+ OCI8::BindType::Mapping[Float] = OCI8::BindType::Float
161
+ OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer
162
+ OCI8::BindType::Mapping[Bignum] = OCI8::BindType::Integer
163
+ OCI8::BindType::Mapping[OraDate] = OCI8::BindType::OraDate
164
+ OCI8::BindType::Mapping[Time] = OCI8::BindType::Time
165
+ OCI8::BindType::Mapping[Date] = OCI8::BindType::Date
166
+ OCI8::BindType::Mapping[DateTime] = OCI8::BindType::DateTime
167
+ OCI8::BindType::Mapping[OCI8::CLOB] = OCI8::BindType::CLOB
168
+ OCI8::BindType::Mapping[OCI8::NCLOB] = OCI8::BindType::NCLOB
169
+ OCI8::BindType::Mapping[OCI8::BLOB] = OCI8::BindType::BLOB
170
+ OCI8::BindType::Mapping[OCI8::BFILE] = OCI8::BindType::BFILE
171
+ OCI8::BindType::Mapping[OCI8::Cursor] = OCI8::BindType::Cursor
172
+
173
+ # implicitly define
174
+
175
+ # datatype type size prec scale
176
+ # -------------------------------------------------
177
+ # CHAR(1) SQLT_AFC 1 0 0
178
+ # CHAR(10) SQLT_AFC 10 0 0
179
+ OCI8::BindType::Mapping[:char] = OCI8::BindType::String
180
+
181
+ # datatype type size prec scale
182
+ # -------------------------------------------------
183
+ # VARCHAR(1) SQLT_CHR 1 0 0
184
+ # VARCHAR(10) SQLT_CHR 10 0 0
185
+ # VARCHAR2(1) SQLT_CHR 1 0 0
186
+ # VARCHAR2(10) SQLT_CHR 10 0 0
187
+ OCI8::BindType::Mapping[:varchar2] = OCI8::BindType::String
188
+
189
+ # datatype type size prec scale
190
+ # -------------------------------------------------
191
+ # RAW(1) SQLT_BIN 1 0 0
192
+ # RAW(10) SQLT_BIN 10 0 0
193
+ OCI8::BindType::Mapping[:raw] = OCI8::BindType::RAW
194
+
195
+ # datatype type size prec scale
196
+ # -------------------------------------------------
197
+ # LONG SQLT_LNG 0 0 0
198
+ OCI8::BindType::Mapping[:long] = OCI8::BindType::Long
199
+
200
+ # datatype type size prec scale
201
+ # -------------------------------------------------
202
+ # LONG RAW SQLT_LBI 0 0 0
203
+ OCI8::BindType::Mapping[:long_raw] = OCI8::BindType::LongRaw
204
+
205
+ # datatype type size prec scale
206
+ # -------------------------------------------------
207
+ # CLOB SQLT_CLOB 4000 0 0
208
+ OCI8::BindType::Mapping[:clob] = OCI8::BindType::CLOB
209
+ OCI8::BindType::Mapping[:nclob] = OCI8::BindType::NCLOB
210
+
211
+ # datatype type size prec scale
212
+ # -------------------------------------------------
213
+ # BLOB SQLT_BLOB 4000 0 0
214
+ OCI8::BindType::Mapping[:blob] = OCI8::BindType::BLOB
215
+
216
+ # datatype type size prec scale
217
+ # -------------------------------------------------
218
+ # BFILE SQLT_BFILE 4000 0 0
219
+ OCI8::BindType::Mapping[:bfile] = OCI8::BindType::BFILE
220
+
221
+ # datatype type size prec scale
222
+ # -------------------------------------------------
223
+ # DATE SQLT_DAT 7 0 0
224
+ OCI8::BindType::Mapping[:date] = OCI8::BindType::Time
225
+
226
+ if OCI8.oracle_client_version >= OCI8::ORAVER_9_0
227
+ OCI8::BindType::Mapping[:timestamp] = OCI8::BindType::Time
228
+ OCI8::BindType::Mapping[:timestamp_tz] = OCI8::BindType::Time
229
+ OCI8::BindType::Mapping[:timestamp_ltz] = OCI8::BindType::Time
230
+ OCI8::BindType::Mapping[:interval_ym] = OCI8::BindType::IntervalYM
231
+ OCI8::BindType::Mapping[:interval_ds] = OCI8::BindType::IntervalDS
232
+ end
233
+
234
+ # datatype type size prec scale
235
+ # -------------------------------------------------
236
+ # ROWID SQLT_RDD 4 0 0
237
+ OCI8::BindType::Mapping[:rowid] = OCI8::BindType::String
238
+
239
+ # datatype type size prec scale
240
+ # -----------------------------------------------------
241
+ # FLOAT SQLT_NUM 22 126 -127
242
+ # FLOAT(1) SQLT_NUM 22 1 -127
243
+ # FLOAT(126) SQLT_NUM 22 126 -127
244
+ # DOUBLE PRECISION SQLT_NUM 22 126 -127
245
+ # REAL SQLT_NUM 22 63 -127
246
+ # NUMBER SQLT_NUM 22 0 0
247
+ # NUMBER(1) SQLT_NUM 22 1 0
248
+ # NUMBER(38) SQLT_NUM 22 38 0
249
+ # NUMBER(1, 0) SQLT_NUM 22 1 0
250
+ # NUMBER(38, 0) SQLT_NUM 22 38 0
251
+ # NUMERIC SQLT_NUM 22 38 0
252
+ # INT SQLT_NUM 22 38 0
253
+ # INTEGER SQLT_NUM 22 38 0
254
+ # SMALLINT SQLT_NUM 22 38 0
255
+ OCI8::BindType::Mapping[:number] = OCI8::BindType::Number
256
+
257
+ # mapping for calculated number values.
258
+ #
259
+ # for example:
260
+ # select col1 * 1.1 from tab1;
261
+ #
262
+ # For Oracle 9.2.0.2 or below, this is also used for NUMBER
263
+ # datatypes that have no explicit setting of their precision
264
+ # and scale.
265
+ #
266
+ # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
267
+ # for ruby-oci8 2.0.
268
+ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
269
+
270
+ # mapping for number without precision and scale.
271
+ #
272
+ # for example:
273
+ # create table tab1 (col1 number);
274
+ # select col1 from tab1;
275
+ #
276
+ # note: This is available only on Oracle 9.2.0.3 or above.
277
+ # see: Oracle 9.2.0.x Patch Set Notes.
278
+ #
279
+ # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
280
+ # for ruby-oci8 2.0.
281
+ OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
282
+
283
+ if defined? OCI8::BindType::BinaryDouble
284
+ OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
285
+ OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::BinaryDouble
286
+ else
287
+ OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::Float
288
+ OCI8::BindType::Mapping[:binary_double] = OCI8::BindType::Float
289
+ end
290
+
291
+ # Cursor
292
+ OCI8::BindType::Mapping[:cursor] = OCI8::BindType::Cursor
293
+
294
+ # XMLType (This mapping will be changed before release.)
295
+ OCI8::BindType::Mapping[:xmltype] = OCI8::BindType::Long