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

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