ruby-oci8 2.1.5.1-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +17 -0
  3. data/COPYING +30 -0
  4. data/COPYING_old +64 -0
  5. data/ChangeLog +2779 -0
  6. data/Makefile +92 -0
  7. data/NEWS +660 -0
  8. data/README.md +43 -0
  9. data/VERSION +1 -0
  10. data/dist-files +91 -0
  11. data/docs/install-binary-package.md +40 -0
  12. data/docs/install-full-client.md +116 -0
  13. data/docs/install-instant-client.md +167 -0
  14. data/docs/platform-specific-issues.md +197 -0
  15. data/docs/report-installation-issue.md +50 -0
  16. data/lib/.document +1 -0
  17. data/lib/dbd/OCI8.rb +591 -0
  18. data/lib/oci8.rb +147 -0
  19. data/lib/oci8.rb.in +147 -0
  20. data/lib/oci8/.document +8 -0
  21. data/lib/oci8/bindtype.rb +350 -0
  22. data/lib/oci8/compat.rb +113 -0
  23. data/lib/oci8/connection_pool.rb +108 -0
  24. data/lib/oci8/cursor.rb +564 -0
  25. data/lib/oci8/datetime.rb +605 -0
  26. data/lib/oci8/encoding-init.rb +79 -0
  27. data/lib/oci8/encoding.yml +537 -0
  28. data/lib/oci8/metadata.rb +2092 -0
  29. data/lib/oci8/object.rb +605 -0
  30. data/lib/oci8/oci8.rb +560 -0
  31. data/lib/oci8/ocihandle.rb +607 -0
  32. data/lib/oci8/oracle_version.rb +143 -0
  33. data/lib/oci8/properties.rb +134 -0
  34. data/lib/oci8lib_200.so +0 -0
  35. data/metaconfig +142 -0
  36. data/pre-distclean.rb +7 -0
  37. data/ruby-oci8.gemspec +80 -0
  38. data/setup.rb +1333 -0
  39. data/test/README +42 -0
  40. data/test/config.rb +184 -0
  41. data/test/setup_test_object.sql +171 -0
  42. data/test/test_all.rb +54 -0
  43. data/test/test_appinfo.rb +63 -0
  44. data/test/test_array_dml.rb +333 -0
  45. data/test/test_bind_raw.rb +46 -0
  46. data/test/test_bind_string.rb +106 -0
  47. data/test/test_bind_time.rb +178 -0
  48. data/test/test_break.rb +124 -0
  49. data/test/test_clob.rb +98 -0
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +81 -0
  52. data/test/test_datetime.rb +581 -0
  53. data/test/test_dbi.rb +366 -0
  54. data/test/test_dbi_clob.rb +53 -0
  55. data/test/test_encoding.rb +104 -0
  56. data/test/test_error.rb +88 -0
  57. data/test/test_metadata.rb +1485 -0
  58. data/test/test_object.rb +462 -0
  59. data/test/test_oci8.rb +489 -0
  60. data/test/test_oracle_version.rb +70 -0
  61. data/test/test_oradate.rb +256 -0
  62. data/test/test_oranumber.rb +787 -0
  63. data/test/test_rowid.rb +33 -0
  64. metadata +109 -0
@@ -0,0 +1,113 @@
1
+ #
2
+ # add compatible code with old versions.
3
+ #
4
+
5
+ OCI_STMT_SELECT = :select_stmt
6
+ OCI_STMT_UPDATE = :update_stmt
7
+ OCI_STMT_DELETE = :delete_stmt
8
+ OCI_STMT_INSERT = :insert_stmt
9
+ OCI_STMT_CREATE = :create_stmt
10
+ OCI_STMT_DROP = :drop_stmt
11
+ OCI_STMT_ALTER = :alter_stmt
12
+ OCI_STMT_BEGIN = :begin_stmt
13
+ OCI_STMT_DECLARE = :declare_stmt
14
+
15
+ class OCI8
16
+
17
+ STMT_SELECT = :select_stmt
18
+ STMT_UPDATE = :update_stmt
19
+ STMT_DELETE = :delete_stmt
20
+ STMT_INSERT = :insert_stmt
21
+ STMT_CREATE = :create_stmt
22
+ STMT_DROP = :drop_stmt
23
+ STMT_ALTER = :alter_stmt
24
+ STMT_BEGIN = :begin_stmt
25
+ STMT_DECLARE = :declare_stmt
26
+
27
+ RAW = :raw
28
+
29
+ # varchar, varchar2
30
+ SQLT_CHR = :varchar2
31
+ # number, double precision, float, real, numeric, int, integer, smallint
32
+ SQLT_NUM = :number
33
+ # long
34
+ SQLT_LNG = :long
35
+ # date
36
+ SQLT_DAT = :date
37
+ # raw
38
+ SQLT_BIN = :raw
39
+ # long raw
40
+ SQLT_LBI = :long_raw
41
+ # char
42
+ SQLT_AFC = :char
43
+ # binary_float
44
+ SQLT_IBFLOAT = :binary_float
45
+ # binary_double
46
+ SQLT_IBDOUBLE = :binary_double
47
+ # rowid
48
+ SQLT_RDD = :rowid
49
+ # clob
50
+ SQLT_CLOB = :clob
51
+ # blob
52
+ SQLT_BLOB = :blob
53
+ # bfile
54
+ SQLT_BFILE = :bfile
55
+ # ref cursor
56
+ SQLT_RSET = 116
57
+ # timestamp
58
+ SQLT_TIMESTAMP = :timestamp
59
+ # timestamp with time zone
60
+ SQLT_TIMESTAMP_TZ = :timestamp_tz
61
+ # interval year to month
62
+ SQLT_INTERVAL_YM = :interval_ym
63
+ # interval day to second
64
+ SQLT_INTERVAL_DS = :interval_ds
65
+ # timestamp with local time zone
66
+ SQLT_TIMESTAMP_LTZ = :timestamp_ltz
67
+
68
+ # mapping of sql type number to sql type name.
69
+ SQLT_NAMES = {}
70
+ constants.each do |name|
71
+ next if name.to_s.index("SQLT_") != 0
72
+ val = const_get name.intern
73
+ if val.is_a? Fixnum
74
+ SQLT_NAMES[val] = name
75
+ end
76
+ end
77
+
78
+ # add alias compatible with 'Oracle7 Module for Ruby'.
79
+ alias autocommit autocommit?
80
+
81
+ class Cursor
82
+ def self.select_number_as=(val)
83
+ if val == Fixnum
84
+ @@bind_unknown_number = OCI8::BindType::Fixnum
85
+ elsif val == Integer
86
+ @@bind_unknown_number = OCI8::BindType::Integer
87
+ elsif val == Float
88
+ @@bind_unknown_number = OCI8::BindType::Float
89
+ else
90
+ raise ArgumentError, "must be Fixnum, Integer or Float"
91
+ end
92
+ end
93
+
94
+ def self.select_number_as
95
+ case @@bind_unknown_number
96
+ when OCI8::BindType::Fixnum
97
+ return Fixnum
98
+ when OCI8::BindType::Integer
99
+ return Integer
100
+ when OCI8::BindType::Float
101
+ return Float
102
+ end
103
+ end
104
+
105
+ # add alias compatible with 'Oracle7 Module for Ruby'.
106
+ alias getColNames get_col_names
107
+ end
108
+
109
+ module BindType
110
+ # alias to Integer for compatibility with ruby-oci8 1.0.
111
+ Fixnum = Integer
112
+ end
113
+ end
@@ -0,0 +1,108 @@
1
+ #--
2
+ # connection_pool.rb -- OCI8::ConnectionPool
3
+ #
4
+ # Copyright (C) 2010 KUBO Takehiro <kubo@jiubao.org>
5
+ #++
6
+
7
+ #
8
+ class OCI8
9
+
10
+ # Connection pooling is the use of a group (the pool) of reusable
11
+ # physical connections by several sessions to balance loads.
12
+ # See: {Oracle Call Interface Manual}[http://docs.oracle.com/cd/E11882_01/appdev.112/e10646/oci09adv.htm#sthref1479]
13
+ #
14
+ # This is equivalent to Oracle JDBC Driver {OCI Connection Pooling}[http://docs.oracle.com/cd/E11882_01/java.112/e16548/ociconpl.htm#JJDBC28789].
15
+ #
16
+ # Usage:
17
+ # # Create a connection pool.
18
+ # # username and password are required to establish an implicit primary session.
19
+ # cpool = OCI8::ConnectionPool.new(1, 5, 2, username, password, database)
20
+ #
21
+ # # Get a session from the pool.
22
+ # # Pass the connection pool to the third argument.
23
+ # conn1 = OCI8.new(username, password, cpool)
24
+ #
25
+ # # Get another session.
26
+ # conn2 = OCI8.new(username, password, cpool)
27
+ #
28
+ class ConnectionPool
29
+
30
+ # Connections idle for more than this time value (in seconds) are
31
+ # terminated, to maintain an optimum number of open
32
+ # connections. If it is zero, the connections are never timed out.
33
+ # The default value is zero.
34
+ #
35
+ # <b>Note:</b> Shrinkage of the pool only occurs when there is a network
36
+ # round trip. If there are no operations, then the connections
37
+ # stay alive.
38
+ #
39
+ # @return [Integer]
40
+ def timeout
41
+ attr_get_ub4(OCI_ATTR_CONN_TIMEOUT)
42
+ end
43
+
44
+ # Changes the timeout in seconds to terminate idle connections.
45
+ #
46
+ # @param [Integer] val
47
+ def timeout=(val)
48
+ attr_set_ub4(OCI_ATTR_CONN_TIMEOUT, val)
49
+ end
50
+
51
+ # If true, an error is thrown when all the connections in the pool
52
+ # are busy and the number of connections has already reached the
53
+ # maximum. Otherwise the call waits till it gets a connection.
54
+ # The default value is false.
55
+ def nowait?
56
+ attr_get_ub1(OCI_ATTR_CONN_NOWAIT) != 0
57
+ end
58
+
59
+ # Changes the behavior when all the connections in the pool
60
+ # are busy and the number of connections has already reached the
61
+ # maximum.
62
+ #
63
+ # @param [Boolean] val
64
+ def nowait=(val)
65
+ attr_set_ub1(OCI_ATTR_CONN_NOWAIT, val ? 1 : 0)
66
+ end
67
+
68
+ # Returns the number of busy physical connections.
69
+ #
70
+ # @return [Integer]
71
+ def busy_count
72
+ attr_get_ub4(OCI_ATTR_CONN_BUSY_COUNT)
73
+ end
74
+
75
+ # Returns the number of open physical connections.
76
+ #
77
+ # @return [Integer]
78
+ def open_count
79
+ attr_get_ub4(OCI_ATTR_CONN_OPEN_COUNT)
80
+ end
81
+
82
+ # Returns the number of minimum physical connections.
83
+ #
84
+ # @return [Integer]
85
+ def min
86
+ attr_get_ub4(OCI_ATTR_CONN_MIN)
87
+ end
88
+
89
+ # Returns the number of maximum physical connections.
90
+ #
91
+ # @return [Integer]
92
+ def max
93
+ attr_get_ub4(OCI_ATTR_CONN_MAX)
94
+ end
95
+
96
+ # Returns the connection increment parameter.
97
+ #
98
+ # @return [Integer]
99
+ def incr
100
+ attr_get_ub4(OCI_ATTR_CONN_INCR)
101
+ end
102
+
103
+ #
104
+ def destroy
105
+ free
106
+ end
107
+ end
108
+ 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