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.
@@ -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