ruby-oci8 2.1.2-x86-mingw32 → 2.1.3-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,22 +23,26 @@ if RUBY_PLATFORM =~ /cygwin/
23
23
  end
24
24
  end
25
25
 
26
- so_basename = 'oci8lib_'
27
- if defined? RUBY_ENGINE and RUBY_ENGINE != 'ruby'
28
- so_basename += RUBY_ENGINE
29
- end
26
+ ruby_engine = (defined? RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
30
27
 
31
- # The suffix number indicates the ruby API version.
32
- # 18 - ruby 1.8.x
33
- # 191 - ruby 1.9.1 and 1.9.2
34
- # 19x - ruby 1.9.x future version which will break the API compatibility
35
- case RUBY_VERSION
36
- when /^1\.9/, /^2\.0/
37
- so_basename += '191'
38
- when /^1\.8/
39
- so_basename += '18'
28
+ so_basename = 'oci8lib_'
29
+ if ruby_engine == 'ruby'
30
+ # The suffix number indicates the ruby API version.
31
+ # 1.8 - ruby 1.8.x
32
+ # 1.9.1 - ruby 1.9.1, 1.9.2
33
+ # 2.0.0 - ruby 2.0.0-dev at the present time.
34
+ case RUBY_VERSION
35
+ when /^2\.0/
36
+ so_basename += '200'
37
+ when /^1\.9/
38
+ so_basename += '191'
39
+ when /^1\.8/
40
+ so_basename += '18'
41
+ else
42
+ raise 'unsupported ruby version: ' + RUBY_VERSION
43
+ end
40
44
  else
41
- raise 'unsupported ruby version: ' + RUBY_VERSION
45
+ so_basename += ruby_engine
42
46
  end
43
47
  require so_basename
44
48
 
@@ -52,19 +56,24 @@ require 'oci8/encoding-init.rb'
52
56
  require 'oci8/oracle_version.rb'
53
57
 
54
58
  class OCI8
59
+ # @private
55
60
  ORAVER_8_0 = OCI8::OracleVersion.new(8, 0)
61
+ # @private
56
62
  ORAVER_8_1 = OCI8::OracleVersion.new(8, 1)
63
+ # @private
57
64
  ORAVER_9_0 = OCI8::OracleVersion.new(9, 0)
65
+ # @private
58
66
  ORAVER_9_2 = OCI8::OracleVersion.new(9, 2)
67
+ # @private
59
68
  ORAVER_10_1 = OCI8::OracleVersion.new(10, 1)
69
+ # @private
60
70
  ORAVER_10_2 = OCI8::OracleVersion.new(10, 2)
71
+ # @private
61
72
  ORAVER_11_1 = OCI8::OracleVersion.new(11, 1)
62
73
 
74
+ # @private
63
75
  @@oracle_client_version = OCI8::OracleVersion.new(self.oracle_client_vernum)
64
76
 
65
- # :call-seq:
66
- # OCI8.oracle_client_version -> oraver
67
- #
68
77
  # Returns an OCI8::OracleVersion of the Oracle client version.
69
78
  #
70
79
  # If this library is configured without '--with-runtime-check',
@@ -78,11 +87,14 @@ class OCI8
78
87
  #
79
88
  # Otherwise, it is the version retrieved from an OCI function
80
89
  # OCIClientVersion().
90
+ #
91
+ # @return [OCI8::OracleVersion] Oracle client version
81
92
  def self.oracle_client_version
82
93
  @@oracle_client_version
83
94
  end
84
95
 
85
96
  # defined for backward compatibility.
97
+ # @private
86
98
  CLIENT_VERSION = @@oracle_client_version.major.to_s +
87
99
  @@oracle_client_version.minor.to_s +
88
100
  @@oracle_client_version.update.to_s
@@ -91,6 +103,7 @@ end
91
103
  require 'oci8/ocihandle.rb'
92
104
  require 'oci8/datetime.rb'
93
105
  require 'oci8/oci8.rb'
106
+ require 'oci8/cursor.rb'
94
107
  require 'oci8/bindtype.rb'
95
108
  require 'oci8/metadata.rb'
96
109
  require 'oci8/compat.rb'
@@ -27,9 +27,6 @@ class OCI8
27
27
  #
28
28
  class ConnectionPool
29
29
 
30
- # call-seq:
31
- # timeout -> integer
32
- #
33
30
  # Connections idle for more than this time value (in seconds) are
34
31
  # terminated, to maintain an optimum number of open
35
32
  # connections. If it is zero, the connections are never timed out.
@@ -38,21 +35,19 @@ class OCI8
38
35
  # <b>Note:</b> Shrinkage of the pool only occurs when there is a network
39
36
  # round trip. If there are no operations, then the connections
40
37
  # stay alive.
38
+ #
39
+ # @return [Integer]
41
40
  def timeout
42
41
  attr_get_ub4(OCI_ATTR_CONN_TIMEOUT)
43
42
  end
44
43
 
45
- # call-seq:
46
- # timeout = integer
47
- #
48
44
  # Changes the timeout in seconds to terminate idle connections.
45
+ #
46
+ # @param [Integer] val
49
47
  def timeout=(val)
50
48
  attr_set_ub4(OCI_ATTR_CONN_TIMEOUT, val)
51
49
  end
52
50
 
53
- # call-seq:
54
- # nowait? -> true or false
55
- #
56
51
  # If true, an error is thrown when all the connections in the pool
57
52
  # are busy and the number of connections has already reached the
58
53
  # maximum. Otherwise the call waits till it gets a connection.
@@ -61,52 +56,46 @@ class OCI8
61
56
  attr_get_ub1(OCI_ATTR_CONN_NOWAIT) != 0
62
57
  end
63
58
 
64
- # call-seq:
65
- # nowait = true or false
66
- #
67
59
  # Changes the behavior when all the connections in the pool
68
60
  # are busy and the number of connections has already reached the
69
61
  # maximum.
62
+ #
63
+ # @param [Boolean] val
70
64
  def nowait=(val)
71
65
  attr_set_ub1(OCI_ATTR_CONN_NOWAIT, val ? 1 : 0)
72
66
  end
73
67
 
74
- # call-seq:
75
- # busy_count -> integer
76
- #
77
68
  # Returns the number of busy physical connections.
69
+ #
70
+ # @return [Integer]
78
71
  def busy_count
79
72
  attr_get_ub4(OCI_ATTR_CONN_BUSY_COUNT)
80
73
  end
81
74
 
82
- # call-seq:
83
- # open_count -> integer
84
- #
85
75
  # Returns the number of open physical connections.
76
+ #
77
+ # @return [Integer]
86
78
  def open_count
87
79
  attr_get_ub4(OCI_ATTR_CONN_OPEN_COUNT)
88
80
  end
89
81
 
90
- # call-seq:
91
- # min -> integer
92
- #
93
82
  # Returns the number of minimum physical connections.
83
+ #
84
+ # @return [Integer]
94
85
  def min
95
86
  attr_get_ub4(OCI_ATTR_CONN_MIN)
96
87
  end
97
88
 
98
- # call-seq:
99
- # max -> integer
100
- #
101
89
  # Returns the number of maximum physical connections.
90
+ #
91
+ # @return [Integer]
102
92
  def max
103
93
  attr_get_ub4(OCI_ATTR_CONN_MAX)
104
94
  end
105
95
 
106
- # call-seq:
107
- # incr -> integer
108
- #
109
96
  # Returns the connection increment parameter.
97
+ #
98
+ # @return [Integer]
110
99
  def incr
111
100
  attr_get_ub4(OCI_ATTR_CONN_INCR)
112
101
  end
@@ -0,0 +1,564 @@
1
+ # oci8.rb -- OCI8::Cursor
2
+ #
3
+ # Copyright (C) 2002-2012 KUBO Takehiro <kubo@jiubao.org>
4
+ #
5
+
6
+ #
7
+ class OCI8
8
+
9
+ # The instance of this class corresponds to cursor in the term of
10
+ # Oracle, which corresponds to java.sql.Statement of JDBC and statement
11
+ # handle $sth of Perl/DBI.
12
+ #
13
+ # Don't create the instance by calling 'new' method. Please create it by
14
+ # calling OCI8#exec or OCI8#parse.
15
+ class Cursor
16
+
17
+ # @note Don't use this constructor. Use {OCI8#parse} instead.
18
+ #
19
+ # @param [OCI8] conn connection
20
+ # @param [String] sql SQL statement
21
+ def initialize(conn, sql = nil)
22
+ @bind_handles = {}
23
+ @define_handles = []
24
+ @column_metadata = []
25
+ @names = nil
26
+ @con = conn
27
+ @max_array_size = nil
28
+ __initialize(conn, sql) # Initialize the internal C structure.
29
+ end
30
+
31
+ # explicitly indicate the date type of fetched value. run this
32
+ # method within parse and exec. pos starts from 1. lentgh is used
33
+ # when type is String.
34
+ #
35
+ # example:
36
+ # cursor = conn.parse("SELECT ename, hiredate FROM emp")
37
+ # cursor.define(1, String, 20) # fetch the first column as String.
38
+ # cursor.define(2, Time) # fetch the second column as Time.
39
+ # cursor.exec()
40
+ def define(pos, type, length = nil)
41
+ bindobj = make_bind_object(:type => type, :length => length)
42
+ __define(pos, bindobj)
43
+ if old = @define_handles[pos - 1]
44
+ old.send(:free)
45
+ end
46
+ @define_handles[pos - 1] = bindobj
47
+ self
48
+ end
49
+
50
+ # Binds variables explicitly.
51
+ #
52
+ # When key is number, it binds by position, which starts from 1.
53
+ # When key is string, it binds by the name of placeholder.
54
+ #
55
+ # example:
56
+ # cursor = conn.parse("SELECT * FROM emp WHERE ename = :ename")
57
+ # cursor.bind_param(1, 'SMITH') # bind by position
58
+ # ...or...
59
+ # cursor.bind_param(':ename', 'SMITH') # bind by name
60
+ #
61
+ # To bind as number, Fixnum and Float are available, but Bignum is
62
+ # not supported. If its initial value is NULL, please set nil to
63
+ # +type+ and Fixnum or Float to +val+.
64
+ #
65
+ # example:
66
+ # cursor.bind_param(1, 1234) # bind as Fixnum, Initial value is 1234.
67
+ # cursor.bind_param(1, 1234.0) # bind as Float, Initial value is 1234.0.
68
+ # cursor.bind_param(1, nil, Fixnum) # bind as Fixnum, Initial value is NULL.
69
+ # cursor.bind_param(1, nil, Float) # bind as Float, Initial value is NULL.
70
+ #
71
+ # In case of binding a string, set the string itself to
72
+ # +val+. When the bind variable is used as output, set the
73
+ # string whose length is enough to store or set the length.
74
+ #
75
+ # example:
76
+ # cursor = conn.parse("BEGIN :out := :in || '_OUT'; END;")
77
+ # cursor.bind_param(':in', 'DATA') # bind as String with width 4.
78
+ # cursor.bind_param(':out', nil, String, 7) # bind as String with width 7.
79
+ # cursor.exec()
80
+ # p cursor[':out'] # => 'DATA_OU'
81
+ # # Though the length of :out is 8 bytes in PL/SQL block, it is
82
+ # # bound as 7 bytes. So result is cut off at 7 byte.
83
+ #
84
+ # In case of binding a string as RAW, set OCI::RAW to +type+.
85
+ #
86
+ # example:
87
+ # cursor = conn.parse("INSERT INTO raw_table(raw_column) VALUE (:1)")
88
+ # cursor.bind_param(1, 'RAW_STRING', OCI8::RAW)
89
+ # cursor.exec()
90
+ # cursor.close()
91
+ def bind_param(key, param, type = nil, length = nil)
92
+ case param
93
+ when Hash
94
+ when Class
95
+ param = {:value => nil, :type => param, :length => length}
96
+ else
97
+ param = {:value => param, :type => type, :length => length}
98
+ end
99
+ bindobj = make_bind_object(param)
100
+ __bind(key, bindobj)
101
+ if old = @bind_handles[key]
102
+ old.send(:free)
103
+ end
104
+ @bind_handles[key] = bindobj
105
+ self
106
+ end
107
+
108
+ # Executes the SQL statement assigned the cursor. The type of
109
+ # return value depends on the type of sql statement: select;
110
+ # insert, update and delete; create, alter, drop and PL/SQL.
111
+ #
112
+ # In case of select statement, it returns the number of the
113
+ # select-list.
114
+ #
115
+ # In case of insert, update or delete statement, it returns the
116
+ # number of processed rows.
117
+ #
118
+ # In case of create, alter, drop and PL/SQL statement, it returns
119
+ # true. In contrast with OCI8#exec, it returns true even
120
+ # though PL/SQL. Use OCI8::Cursor#[] explicitly to get bind
121
+ # variables.
122
+ def exec(*bindvars)
123
+ bind_params(*bindvars)
124
+ case type
125
+ when :select_stmt
126
+ __execute(0)
127
+ define_columns()
128
+ else
129
+ __execute(1)
130
+ row_count
131
+ end
132
+ end
133
+
134
+ # Gets fetched data as array. This is available for select
135
+ # statement only.
136
+ #
137
+ # @example
138
+ # conn = OCI8.new('scott', 'tiger')
139
+ # cursor = conn.exec('SELECT * FROM emp')
140
+ # while r = cursor.fetch()
141
+ # puts r.join(',')
142
+ # end
143
+ # cursor.close
144
+ # conn.logoff
145
+ #
146
+ # @return [Array]
147
+ def fetch
148
+ if block_given?
149
+ while row = fetch_one_row_as_array
150
+ yield row
151
+ end
152
+ self
153
+ else
154
+ fetch_one_row_as_array
155
+ end
156
+ end
157
+
158
+ # Gets fetched data as a Hash. The hash keys are column names.
159
+ # If a block is given, acts as an iterator.
160
+ #
161
+ # @return [Hash] the hash keys are column names and hash values are column values
162
+ def fetch_hash
163
+ if block_given?
164
+ while row = fetch_one_row_as_hash()
165
+ yield row
166
+ end
167
+ else
168
+ fetch_one_row_as_hash
169
+ end
170
+ end
171
+
172
+ # Gets the value of the bind variable.
173
+ #
174
+ # When bind variables are explicitly bound by {OCI8::Cursor#bind_param},
175
+ # the subscript +key+ must be same with the parameter +key+ passed to {OCI8::Cursor#bind_param}.
176
+ #
177
+ # When they are implicitly bound by {OCI8#exec} or {OCI8::Cursor#exec},
178
+ # the subscript +key+ is the position which starts from one.
179
+ #
180
+ # @example explicitly bind by name
181
+ # cursor = conn.parse("BEGIN :out := 'BAR'; END;")
182
+ # cursor.bind_param(:out, 'FOO') # bind by name
183
+ # p cursor[:out] # => 'FOO' - The subscript must be :out.
184
+ # cursor.exec()
185
+ # p cursor[:out] # => 'BAR'
186
+ #
187
+ # @example explicitly bind by position
188
+ # cursor = conn.parse("BEGIN :out := 'BAR'; END;")
189
+ # cursor.bind_param(1, 'FOO') # bind by position
190
+ # p cursor[1] # => 'FOO' - The subscript must be 1.
191
+ # cursor.exec()
192
+ # p cursor[1] # => 'BAR'
193
+ #
194
+ # @example implicitly bind
195
+ # cursor = conn.exec("BEGIN :out := 'BAR'; END;", 'FOO')
196
+ # # 1st bind variable is bound as String with width 3. Its initial value is 'FOO'
197
+ # # After execute, the value become 'BAR'.
198
+ # p cursor[1] # => 'BAR'
199
+ #
200
+ # @param [Object] key bind key
201
+ # @return [Object] the value of the bind variable
202
+ #
203
+ def [](key)
204
+ handle = @bind_handles[key]
205
+ handle && handle.send(:get_data)
206
+ end
207
+
208
+ # Changes the bind variable value.
209
+ #
210
+ # When bind variables are explicitly bound by {OCI8::Cursor#bind_param},
211
+ # the subscript +key+ must be same with the parameter +key+ passed to {OCI8::Cursor#bind_param}.
212
+ #
213
+ # When they are implicitly bound by {OCI8#exec} or {OCI8::Cursor#exec},
214
+ # the subscript +key+ is the position which starts from one.
215
+ #
216
+ # @example
217
+ # # Inserts three rows whose values are 'FOO', 'BAR' and 'BAZ.'
218
+ # cursor = conn.parse("INSERT INTO test(col1) VALUES(:1)")
219
+ # begin
220
+ # cursor.bind_params(1, nil, String, 3)
221
+ # ['FOO', 'BAR', 'BAZ'].each do |column_value|
222
+ # cursor[1] = column_value # Change the bind value
223
+ # cursor.exec # and insert it.
224
+ # end
225
+ # ensure
226
+ # cursor.close()
227
+ # end
228
+ # # This makes same result with the following but is more efficient.
229
+ # #
230
+ # # ['FOO', 'BAR', 'BAZ'].each do |column_value|
231
+ # # conn.exec("INSERT INTO test(col1) VALUES(:1)", column_value)
232
+ # # end
233
+ # #
234
+ #
235
+ # @param [Object] key bind key
236
+ # @param [Object] val bind value
237
+ #
238
+ def []=(key, val)
239
+ handle = @bind_handles[key]
240
+ return nil if handle.nil?
241
+
242
+ if val.is_a? Array
243
+ if @actual_array_size > 0 && val.length != @actual_array_size
244
+ raise RuntimeError, "all binding arrays hould be the same size"
245
+ end
246
+ if @actual_array_size == 0 && val.length <= @max_array_size
247
+ @actual_array_size = val.length
248
+ end
249
+ end
250
+ handle.send(:set_data, val)
251
+ val
252
+ end
253
+
254
+ # Set the maximum array size for bind_param_array
255
+ #
256
+ # All the binds will be clean from cursor if instance variable max_array_size is set before
257
+ #
258
+ # Instance variable actual_array_size holds the size of the arrays users actually binds through bind_param_array
259
+ # all the binding arrays are required to be the same size
260
+ def max_array_size=(size)
261
+ raise "expect positive number for max_array_size." if size.nil? && size <=0
262
+ free_bind_handles() if !@max_array_size.nil?
263
+ @max_array_size = size
264
+ @actual_array_size = nil
265
+ end
266
+
267
+ # Binds array explicitly
268
+ #
269
+ # When key is number, it binds by position, which starts from 1.
270
+ # When key is string, it binds by the name of placeholder.
271
+ #
272
+ # The max_array_size should be set before calling bind_param_array
273
+ #
274
+ # @example
275
+ # cursor = conn.parse("INSERT INTO test_table VALUES (:str)")
276
+ # cursor.max_array_size = 3
277
+ # cursor.bind_param_array(1, ['happy', 'new', 'year'], String, 30)
278
+ # cursor.exec_array
279
+ def bind_param_array(key, var_array, type = nil, max_item_length = nil)
280
+ raise "please call max_array_size= first." if @max_array_size.nil?
281
+ raise "expect array as input param for bind_param_array." if !var_array.nil? && !(var_array.is_a? Array)
282
+ raise "the size of var_array should not be greater than max_array_size." if !var_array.nil? && var_array.size > @max_array_size
283
+
284
+ if var_array.nil?
285
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || @actual_array_size == 0
286
+ @actual_array_size = 0
287
+ else
288
+ raise "all binding arrays should be the same size." unless @actual_array_size.nil? || var_array.size == @actual_array_size
289
+ @actual_array_size = var_array.size if @actual_array_size.nil?
290
+ end
291
+
292
+ param = {:value => var_array, :type => type, :length => max_item_length, :max_array_size => @max_array_size}
293
+ first_non_nil_elem = var_array.nil? ? nil : var_array.find{|x| x!= nil}
294
+
295
+ if type.nil?
296
+ if first_non_nil_elem.nil?
297
+ raise "bind type is not given."
298
+ else
299
+ type = first_non_nil_elem.class
300
+ end
301
+ end
302
+
303
+ bindclass = OCI8::BindType::Mapping[type]
304
+ if bindclass.nil? and type.is_a? Class
305
+ bindclass = OCI8::BindType::Mapping[type.to_s]
306
+ OCI8::BindType::Mapping[type] = bindclass if bindclass
307
+ end
308
+ raise "unsupported dataType: #{type}" if bindclass.nil?
309
+ bindobj = bindclass.create(@con, var_array, param, @max_array_size)
310
+ __bind(key, bindobj)
311
+ #
312
+ if old = @bind_handles[key]
313
+ old.send(:free)
314
+ end
315
+ @bind_handles[key] = bindobj
316
+ self
317
+ end
318
+
319
+ # Executes the SQL statement assigned the cursor with array binding
320
+ def exec_array
321
+ raise "please call max_array_size= first." if @max_array_size.nil?
322
+
323
+ if !@actual_array_size.nil? && @actual_array_size > 0
324
+ __execute(@actual_array_size)
325
+ else
326
+ raise "please set non-nil values to array binding parameters"
327
+ end
328
+
329
+ case type
330
+ when :update_stmt, :delete_stmt, :insert_stmt
331
+ row_count
332
+ else
333
+ true
334
+ end
335
+ end
336
+
337
+ # Gets the names of select-list as array. Please use this
338
+ # method after exec.
339
+ def get_col_names
340
+ @names ||= @column_metadata.collect { |md| md.name }
341
+ end
342
+
343
+ # Gets an array of OCI8::Metadata::Column of a select statement.
344
+ #
345
+ # @example
346
+ # cursor = conn.exec('select * from tab')
347
+ # puts ' Name Type'
348
+ # puts ' ----------------------------------------- ----------------------------'
349
+ # cursor.column_metadata.each do |colinfo|
350
+ # puts format(' %-41s %s',
351
+ # colinfo.name,
352
+ # colinfo.type_string)
353
+ # end
354
+ #
355
+ # @return [Array of OCI8::Metadata::Column]
356
+ #
357
+ # @since 1.0.0
358
+ def column_metadata
359
+ @column_metadata
360
+ end
361
+
362
+ # close the cursor.
363
+ def close
364
+ free()
365
+ @names = nil
366
+ @column_metadata = nil
367
+ end
368
+
369
+ # Returns the keys of bind variables.
370
+ #
371
+ # @return [Array] bind variable keys
372
+ def keys
373
+ @bind_handles.keys
374
+ end
375
+
376
+ # Set the number of rows to be prefetched.
377
+ # This can reduce the number of network round trips when fetching
378
+ # many rows. The default value is one.
379
+ #
380
+ # FYI: Rails oracle adaptor uses 100 by default.
381
+ #
382
+ # @param [Fixnum] rows The number of rows to be prefetched
383
+ def prefetch_rows=(rows)
384
+ attr_set_ub4(11, rows) # OCI_ATTR_PREFETCH_ROWS(11)
385
+ end
386
+
387
+ # Returns the number of processed rows.
388
+ #
389
+ # @return [Integer]
390
+ def row_count
391
+ # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5498
392
+ attr_get_ub4(9) # OCI_ATTR_ROW_COUNT(9)
393
+ end
394
+
395
+ # Returns the text of the SQL statement prepared in the cursor.
396
+ #
397
+ # @note
398
+ # When {http://docs.oracle.com/cd/E11882_01/server.112/e10729/ch7progrunicode.htm#CACHHIFE
399
+ # NCHAR String Literal Replacement} is turned on, it returns the modified SQL text,
400
+ # instead of the original SQL text.
401
+ #
402
+ # @example
403
+ # cursor = conn.parse("select * from country where country_code = 'ja'")
404
+ # cursor.statement # => "select * from country where country_code = 'ja'"
405
+ #
406
+ # @return [String] prepared SQL statement
407
+ #
408
+ # @since 2.1.3
409
+ #
410
+ def statement
411
+ # The magic number 144 is OCI_ATTR_STATEMENT.
412
+ # See http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5503
413
+ attr_get_string(144)
414
+ end
415
+
416
+ # gets the type of SQL statement as follows.
417
+ # * OCI8::STMT_SELECT
418
+ # * OCI8::STMT_UPDATE
419
+ # * OCI8::STMT_DELETE
420
+ # * OCI8::STMT_INSERT
421
+ # * OCI8::STMT_CREATE
422
+ # * OCI8::STMT_DROP
423
+ # * OCI8::STMT_ALTER
424
+ # * OCI8::STMT_BEGIN (PL/SQL block which starts with a BEGIN keyword)
425
+ # * OCI8::STMT_DECLARE (PL/SQL block which starts with a DECLARE keyword)
426
+ # * Other Fixnum value undocumented in Oracle manuals.
427
+ #
428
+ # <em>Changes between ruby-oci8 1.0 and 2.0.</em>
429
+ #
430
+ # [ruby-oci8 2.0] OCI8::STMT_* are Symbols. (:select_stmt, :update_stmt, etc.)
431
+ # [ruby-oci8 1.0] OCI8::STMT_* are Fixnums. (1, 2, 3, etc.)
432
+ #
433
+ def type
434
+ # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5506
435
+ stmt_type = attr_get_ub2(24) # OCI_ATTR_STMT_TYPE(24)
436
+ case stmt_type
437
+ when 1 # OCI_STMT_SELECT
438
+ :select_stmt
439
+ when 2 # OCI_STMT_UPDATE
440
+ :update_stmt
441
+ when 3 # OCI_STMT_DELETE
442
+ :delete_stmt
443
+ when 4 # OCI_STMT_INSERT
444
+ :insert_stmt
445
+ when 5 # OCI_STMT_CREATE
446
+ :create_stmt
447
+ when 6 # OCI_STMT_DROP
448
+ :drop_stmt
449
+ when 7 # OCI_STMT_ALTER
450
+ :alter_stmt
451
+ when 8 # OCI_STMT_BEGIN
452
+ :begin_stmt
453
+ when 9 # OCI_STMT_DECLARE
454
+ :declare_stmt
455
+ else
456
+ stmt_type
457
+ end
458
+ end
459
+
460
+ private
461
+
462
+ def make_bind_object(param)
463
+ case param
464
+ when Hash
465
+ key = param[:type]
466
+ val = param[:value]
467
+ max_array_size = param[:max_array_size]
468
+
469
+ if key.nil?
470
+ if val.nil?
471
+ raise "bind type is not given."
472
+ elsif val.is_a? OCI8::Object::Base
473
+ key = :named_type
474
+ param = @con.get_tdo_by_class(val.class)
475
+ else
476
+ key = val.class
477
+ end
478
+ elsif key.class == Class && key < OCI8::Object::Base
479
+ param = @con.get_tdo_by_class(key)
480
+ key = :named_type
481
+ end
482
+ when OCI8::Metadata::Base
483
+ key = param.data_type
484
+ case key
485
+ when :named_type
486
+ if param.type_name == 'XMLTYPE'
487
+ key = :xmltype
488
+ else
489
+ param = @con.get_tdo_by_metadata(param.type_metadata)
490
+ end
491
+ end
492
+ else
493
+ raise "unknown param #{param.intern}"
494
+ end
495
+
496
+ bindclass = OCI8::BindType::Mapping[key]
497
+ if bindclass.nil? and key.is_a? Class
498
+ bindclass = OCI8::BindType::Mapping[key.to_s]
499
+ OCI8::BindType::Mapping[key] = bindclass if bindclass
500
+ end
501
+ raise "unsupported datatype: #{key}" if bindclass.nil?
502
+ bindclass.create(@con, val, param, max_array_size)
503
+ end
504
+
505
+ def define_columns
506
+ # http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/ociaahan.htm#sthref5494
507
+ num_cols = attr_get_ub4(18) # OCI_ATTR_PARAM_COUNT(18)
508
+ 1.upto(num_cols) do |i|
509
+ parm = __paramGet(i)
510
+ define_one_column(i, parm) unless @define_handles[i - 1]
511
+ @column_metadata[i - 1] = parm
512
+ end
513
+ num_cols
514
+ end
515
+
516
+ def define_one_column(pos, param)
517
+ bindobj = make_bind_object(param)
518
+ __define(pos, bindobj)
519
+ if old = @define_handles[pos - 1]
520
+ old.send(:free)
521
+ end
522
+ @define_handles[pos - 1] = bindobj
523
+ end
524
+
525
+ def bind_params(*bindvars)
526
+ bindvars.each_with_index do |val, i|
527
+ if val.is_a? Array
528
+ bind_param(i + 1, val[0], val[1], val[2])
529
+ else
530
+ bind_param(i + 1, val)
531
+ end
532
+ end
533
+ end
534
+
535
+ def fetch_one_row_as_array
536
+ if __fetch(@con)
537
+ @define_handles.collect do |handle|
538
+ handle.send(:get_data)
539
+ end
540
+ else
541
+ nil
542
+ end
543
+ end
544
+
545
+ def fetch_one_row_as_hash
546
+ if __fetch(@con)
547
+ ret = {}
548
+ get_col_names.each_with_index do |name, idx|
549
+ ret[name] = @define_handles[idx].send(:get_data)
550
+ end
551
+ ret
552
+ else
553
+ nil
554
+ end
555
+ end
556
+
557
+ def free_bind_handles
558
+ @bind_handles.each_value do |val|
559
+ val.send(:free)
560
+ end
561
+ @bind_handles.clear
562
+ end
563
+ end
564
+ end