ruby-oci8 1.0.2-i386-mswin32
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.
- data/ChangeLog +569 -0
- data/Makefile +51 -0
- data/NEWS +322 -0
- data/README +415 -0
- data/VERSION +1 -0
- data/dist-files +70 -0
- data/doc/api.en.html +527 -0
- data/doc/api.en.rd +554 -0
- data/doc/api.ja.html +525 -0
- data/doc/api.ja.rd +557 -0
- data/doc/manual.css +35 -0
- data/ext/oci8/oci8lib.so +0 -0
- data/lib/DBD/OCI8/OCI8.rb +549 -0
- data/lib/oci8.rb +1605 -0
- data/lib/oci8.rb.in +1605 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +54 -0
- data/ruby-oci8.spec +62 -0
- data/setup.rb +1331 -0
- data/support/README +4 -0
- data/support/runit/assert.rb +281 -0
- data/support/runit/cui/testrunner.rb +101 -0
- data/support/runit/error.rb +4 -0
- data/support/runit/method_mappable.rb +20 -0
- data/support/runit/robserver.rb +25 -0
- data/support/runit/setuppable.rb +15 -0
- data/support/runit/teardownable.rb +16 -0
- data/support/runit/testcase.rb +113 -0
- data/support/runit/testfailure.rb +25 -0
- data/support/runit/testresult.rb +121 -0
- data/support/runit/testsuite.rb +43 -0
- data/support/runit/version.rb +3 -0
- data/test/README +4 -0
- data/test/config.rb +129 -0
- data/test/test_all.rb +43 -0
- data/test/test_bind_raw.rb +53 -0
- data/test/test_bind_time.rb +191 -0
- data/test/test_break.rb +81 -0
- data/test/test_clob.rb +101 -0
- data/test/test_connstr.rb +80 -0
- data/test/test_dbi.rb +317 -0
- data/test/test_dbi_clob.rb +56 -0
- data/test/test_describe.rb +137 -0
- data/test/test_metadata.rb +243 -0
- data/test/test_oci8.rb +273 -0
- data/test/test_oradate.rb +263 -0
- data/test/test_oranumber.rb +149 -0
- metadata +97 -0
data/doc/manual.css
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
h1 {
|
2
|
+
color: #000080;
|
3
|
+
background: #e0e0ff;
|
4
|
+
border-color: #8080d0;
|
5
|
+
border-style: solid;
|
6
|
+
border-top-style: none;
|
7
|
+
border-left-style: none;
|
8
|
+
border-bottom-width: thick;
|
9
|
+
border-right-width: thin;
|
10
|
+
padding-top: 0.2em;
|
11
|
+
padding-bottom: 0.2em;
|
12
|
+
text-align: center
|
13
|
+
}
|
14
|
+
h2 {
|
15
|
+
color: #000080;
|
16
|
+
background: #e0e0ff;
|
17
|
+
border-color: #8080d0;
|
18
|
+
border-style: solid;
|
19
|
+
border-top-style: none;
|
20
|
+
border-left-style: none;
|
21
|
+
border-bottom-width: thick;
|
22
|
+
border-right-width: thin;
|
23
|
+
}
|
24
|
+
code {
|
25
|
+
color: blue
|
26
|
+
}
|
27
|
+
var {
|
28
|
+
color: brown
|
29
|
+
}
|
30
|
+
dt {
|
31
|
+
color: red
|
32
|
+
}
|
33
|
+
pre {
|
34
|
+
background: #e0ffff
|
35
|
+
}
|
data/ext/oci8/oci8lib.so
ADDED
Binary file
|
@@ -0,0 +1,549 @@
|
|
1
|
+
#
|
2
|
+
# DBD::OCI8
|
3
|
+
#
|
4
|
+
# Copyright (c) 2002-2007 KUBO Takehiro <kubo@jiubao.org>
|
5
|
+
#
|
6
|
+
# copied some code from DBD::Oracle.
|
7
|
+
# DBD::Oracle's copyright is as follows:
|
8
|
+
# --------------------- begin -------------------
|
9
|
+
#
|
10
|
+
# Copyright (c) 2001, 2002, 2003, 2004 Michael Neumann <mneumann@ntecs.de>
|
11
|
+
#
|
12
|
+
# All rights reserved.
|
13
|
+
#
|
14
|
+
# Redistribution and use in source and binary forms, with or without
|
15
|
+
# modification, are permitted provided that the following conditions
|
16
|
+
# are met:
|
17
|
+
# 1. Redistributions of source code must retain the above copyright
|
18
|
+
# notice, this list of conditions and the following disclaimer.
|
19
|
+
# 2. Redistributions in binary form must reproduce the above copyright
|
20
|
+
# notice, this list of conditions and the following disclaimer in the
|
21
|
+
# documentation and/or other materials provided with the distribution.
|
22
|
+
# 3. The name of the author may not be used to endorse or promote products
|
23
|
+
# derived from this software without specific prior written permission.
|
24
|
+
#
|
25
|
+
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
26
|
+
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
27
|
+
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
28
|
+
# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
29
|
+
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
30
|
+
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
31
|
+
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
32
|
+
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
33
|
+
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
34
|
+
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
35
|
+
#
|
36
|
+
# --------------------- end -------------------
|
37
|
+
|
38
|
+
require 'oci8'
|
39
|
+
|
40
|
+
module DBI # :nodoc:
|
41
|
+
module DBD # :nodoc:
|
42
|
+
module OCI8
|
43
|
+
|
44
|
+
VERSION = "0.1"
|
45
|
+
USED_DBD_VERSION = "0.2"
|
46
|
+
|
47
|
+
module Util
|
48
|
+
|
49
|
+
ERROR_MAP = {
|
50
|
+
1 => DBI::IntegrityError, # unique constraint violated
|
51
|
+
900 => DBI::ProgrammingError, # invalid SQL statement
|
52
|
+
904 => DBI::ProgrammingError, # invalid identifier
|
53
|
+
905 => DBI::ProgrammingError, # missing keyword
|
54
|
+
923 => DBI::ProgrammingError, # FROM keyword not found where expected
|
55
|
+
936 => DBI::ProgrammingError, # missing expression
|
56
|
+
942 => DBI::ProgrammingError, # table or view does not exist
|
57
|
+
2290 => DBI::IntegrityError, # check constraint violated
|
58
|
+
2291 => DBI::IntegrityError, # parent key not found
|
59
|
+
2292 => DBI::IntegrityError, # child record found
|
60
|
+
2293 => DBI::IntegrityError, # check constraint violated
|
61
|
+
}
|
62
|
+
|
63
|
+
def raise_dbierror(err) # :nodoc:
|
64
|
+
if err.is_a? OCIError
|
65
|
+
exc = ERROR_MAP[err.code] || DBI::DatabaseError
|
66
|
+
raise exc.new(err.message, err.code)
|
67
|
+
else
|
68
|
+
raise DBI::DatabaseError.new(err.message, -1)
|
69
|
+
end
|
70
|
+
rescue DBI::DatabaseError => exc
|
71
|
+
exc.set_backtrace(err.backtrace)
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
|
75
|
+
def column_metadata_to_column_info(col)
|
76
|
+
sql_type, type_name, precision, scale =
|
77
|
+
case col.data_type
|
78
|
+
when :char
|
79
|
+
[SQL_CHAR, col.charset_form == :nchar ? "NCHAR" : "CHAR", col.data_size, nil]
|
80
|
+
when :varchar2
|
81
|
+
[SQL_VARCHAR, col.charset_form == :nchar ? "NVARCHAR2" : "VARCHAR2", col.data_size, nil]
|
82
|
+
when :raw
|
83
|
+
[SQL_VARBINARY, "RAW", col.data_size, nil]
|
84
|
+
when :long
|
85
|
+
[SQL_LONGVARCHAR, "LONG", 4000, nil]
|
86
|
+
when :long_raw
|
87
|
+
[SQL_LONGVARBINARY, "LONG RAW", 4000, nil]
|
88
|
+
when :clob
|
89
|
+
[SQL_CLOB, col.charset_form == :nchar ? "NCLOB" : "CLOB", 4000, nil]
|
90
|
+
when :blob
|
91
|
+
[SQL_BLOB, "BLOB", 4000, nil]
|
92
|
+
when :bfile
|
93
|
+
[SQL_BLOB, "BFILE", 4000, nil]
|
94
|
+
when :number
|
95
|
+
if col.scale == -127 && col.precision != 0
|
96
|
+
# To convert from binary to decimal precision, multiply n by 0.30103.
|
97
|
+
[SQL_FLOAT, "FLOAT", (col.precision * 0.30103).ceil , nil]
|
98
|
+
elsif col.precision == 0
|
99
|
+
# NUMBER or calculated value (eg. col * 1.2).
|
100
|
+
[SQL_NUMERIC, "NUMBER", 38, nil]
|
101
|
+
else
|
102
|
+
[SQL_NUMERIC, "NUMBER", col.precision, col.scale]
|
103
|
+
end
|
104
|
+
when :binary_float
|
105
|
+
# (23 * 0.30103).ceil => 7
|
106
|
+
[SQL_FLOAT, "BINARY_FLOAT", 7, nil]
|
107
|
+
when :binary_double
|
108
|
+
# (52 * 0.30103).ceil => 16
|
109
|
+
[SQL_DOUBLE, "BINARY_DOUBLE", 16, nil]
|
110
|
+
when :date
|
111
|
+
# yyyy-mm-dd hh:mi:ss
|
112
|
+
[SQL_DATE, "DATE", 19, nil]
|
113
|
+
when :timestamp
|
114
|
+
# yyyy-mm-dd hh:mi:ss.SSSS
|
115
|
+
[SQL_TIMESTAMP, "TIMESTAMP", 20 + col.fsprecision, nil]
|
116
|
+
when :timestamp_tz
|
117
|
+
# yyyy-mm-dd hh:mi:ss.SSSS +HH:MM
|
118
|
+
[SQL_TIMESTAMP, "TIMESTAMP WITH TIME ZONE", 27 + col.fsprecision, nil]
|
119
|
+
when :timestamp_ltz
|
120
|
+
# yyyy-mm-dd hh:mi:ss.SSSS
|
121
|
+
[SQL_TIMESTAMP, "TIMESTAMP WITH LOCAL TIME ZONE", 20 + col.fsprecision, nil]
|
122
|
+
when :interval_ym
|
123
|
+
# yyyy-mm
|
124
|
+
[SQL_OTHER, 'INTERVAL YEAR TO MONTH', col.lfprecision + 3, nil]
|
125
|
+
when :interval_ds
|
126
|
+
# dd hh:mi:ss.SSSSS
|
127
|
+
[SQL_OTHER, 'INTERVAL DAY TO SECOND', col.lfprecision + 10 + col.fsprecision, nil]
|
128
|
+
else
|
129
|
+
[SQL_OTHER, col.data_type.to_s, nil, nil]
|
130
|
+
end
|
131
|
+
{'name' => col.name,
|
132
|
+
'sql_type' => sql_type,
|
133
|
+
'type_name' => type_name,
|
134
|
+
'nullable' => col.nullable?,
|
135
|
+
'precision' => precision,
|
136
|
+
'scale' => scale,
|
137
|
+
}
|
138
|
+
end
|
139
|
+
private :column_metadata_to_column_info
|
140
|
+
end
|
141
|
+
|
142
|
+
class Driver < DBI::BaseDriver # :nodoc:
|
143
|
+
include Util
|
144
|
+
|
145
|
+
def initialize
|
146
|
+
super(USED_DBD_VERSION)
|
147
|
+
end
|
148
|
+
|
149
|
+
# external OS authentication
|
150
|
+
# (contributed by Dan Fitch)
|
151
|
+
def default_user
|
152
|
+
[nil, nil]
|
153
|
+
end
|
154
|
+
|
155
|
+
def connect( dbname, user, auth, attr )
|
156
|
+
handle = ::OCI8.new(user, auth, dbname, attr['Privilege'])
|
157
|
+
handle.non_blocking = true if attr['NonBlocking']
|
158
|
+
return Database.new(handle, attr)
|
159
|
+
rescue OCIException => err
|
160
|
+
raise_dbierror(err)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
class Database < DBI::BaseDatabase
|
165
|
+
include Util
|
166
|
+
|
167
|
+
def disconnect
|
168
|
+
@handle.logoff
|
169
|
+
rescue OCIException => err
|
170
|
+
raise_dbierror(err)
|
171
|
+
end
|
172
|
+
|
173
|
+
def prepare( statement )
|
174
|
+
# convert ?-style parameters to :1, :2 etc.
|
175
|
+
prep_statement = DBI::SQL::PreparedStatement.new(DummyQuoter.new, statement)
|
176
|
+
if prep_statement.unbound.size > 0
|
177
|
+
arr = (1..(prep_statement.unbound.size)).collect{|i| ":#{i}"}
|
178
|
+
statement = prep_statement.bind( arr )
|
179
|
+
end
|
180
|
+
cursor = @handle.parse(statement)
|
181
|
+
Statement.new(cursor)
|
182
|
+
rescue OCIException => err
|
183
|
+
raise_dbierror(err)
|
184
|
+
end
|
185
|
+
|
186
|
+
def ping
|
187
|
+
@handle.exec("BEGIN NULL; END;")
|
188
|
+
true
|
189
|
+
rescue
|
190
|
+
false
|
191
|
+
end
|
192
|
+
|
193
|
+
def commit
|
194
|
+
@handle.commit()
|
195
|
+
rescue OCIException => err
|
196
|
+
raise_dbierror(err)
|
197
|
+
end
|
198
|
+
|
199
|
+
def rollback
|
200
|
+
@handle.rollback()
|
201
|
+
rescue OCIException => err
|
202
|
+
raise_dbierror(err)
|
203
|
+
end
|
204
|
+
|
205
|
+
def tables
|
206
|
+
stmt = execute("SELECT object_name FROM user_objects where object_type in ('TABLE', 'VIEW')")
|
207
|
+
rows = stmt.fetch_all || []
|
208
|
+
stmt.finish
|
209
|
+
rows.collect {|row| row[0]}
|
210
|
+
end
|
211
|
+
|
212
|
+
# SQLs are copied from DBD::Oracle.
|
213
|
+
def columns(table)
|
214
|
+
tab = @handle.describe_table(table)
|
215
|
+
cols = tab.columns
|
216
|
+
cols.collect! do |col|
|
217
|
+
column_metadata_to_column_info(col)
|
218
|
+
end
|
219
|
+
|
220
|
+
dbh = DBI::DatabaseHandle.new(self)
|
221
|
+
|
222
|
+
pk_index_name = nil
|
223
|
+
dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name) do |row|
|
224
|
+
select index_name
|
225
|
+
from all_constraints
|
226
|
+
where constraint_type = 'P'
|
227
|
+
and owner = :1
|
228
|
+
and table_name = :2
|
229
|
+
EOS
|
230
|
+
pk_index_name = row[0]
|
231
|
+
end
|
232
|
+
|
233
|
+
indices = {}
|
234
|
+
primaries = {}
|
235
|
+
uniques = {}
|
236
|
+
dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name) do |row|
|
237
|
+
select a.column_name, a.index_name, b.uniqueness
|
238
|
+
from all_ind_columns a, all_indexes b
|
239
|
+
where a.index_name = b.index_name
|
240
|
+
and a.index_owner = b.owner
|
241
|
+
and a.table_owner = :1
|
242
|
+
and a.table_name = :2
|
243
|
+
EOS
|
244
|
+
col_name, index_name, uniqueness = row
|
245
|
+
indices[col_name] = true
|
246
|
+
primaries[col_name] = true if index_name == pk_index_name
|
247
|
+
uniques[col_name] = true if uniqueness == 'UNIQUE'
|
248
|
+
end
|
249
|
+
|
250
|
+
dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name).collect do |row|
|
251
|
+
select column_id, column_name, data_default
|
252
|
+
from all_tab_columns
|
253
|
+
where owner = :1
|
254
|
+
and table_name = :2
|
255
|
+
EOS
|
256
|
+
col_id, col_name, default = row
|
257
|
+
|
258
|
+
col = cols[col_id.to_i - 1]
|
259
|
+
col_name = col['name']
|
260
|
+
|
261
|
+
if default && default[0] == ?'
|
262
|
+
default = default[1..-2].gsub(/''/, "'")
|
263
|
+
end
|
264
|
+
|
265
|
+
col['indexed'] = indices[col_name] || false
|
266
|
+
col['primary'] = primaries[col_name] || false
|
267
|
+
col['unique'] = uniques[col_name] || false
|
268
|
+
col['default'] = default
|
269
|
+
col
|
270
|
+
end
|
271
|
+
rescue OCIException => err
|
272
|
+
raise_dbierror(err)
|
273
|
+
end
|
274
|
+
|
275
|
+
def [](attr)
|
276
|
+
case attr
|
277
|
+
when 'AutoCommit'
|
278
|
+
@handle.autocommit?
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def []=(attr, value)
|
283
|
+
case attr
|
284
|
+
when 'AutoCommit'
|
285
|
+
@handle.autocommit = value
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
private
|
290
|
+
|
291
|
+
class DummyQuoter # :nodoc:
|
292
|
+
# dummy to substitute ?-style parameter markers by :1 :2 etc.
|
293
|
+
def quote(str)
|
294
|
+
str
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
class Statement < DBI::BaseStatement
|
300
|
+
include Util
|
301
|
+
|
302
|
+
def initialize(cursor)
|
303
|
+
@cursor = cursor
|
304
|
+
end
|
305
|
+
|
306
|
+
def bind_param( param, value, attribs)
|
307
|
+
if attribs.nil? || attribs['type'].nil?
|
308
|
+
if value.nil?
|
309
|
+
@cursor.bind_param(param, nil, String, 1)
|
310
|
+
else
|
311
|
+
@cursor.bind_param(param, value)
|
312
|
+
end
|
313
|
+
else
|
314
|
+
case attribs['type']
|
315
|
+
when SQL_BINARY
|
316
|
+
type = OCI_TYPECODE_RAW
|
317
|
+
else
|
318
|
+
type = attribs['type']
|
319
|
+
end
|
320
|
+
@cursor.bind_param(param, value, type)
|
321
|
+
end
|
322
|
+
rescue OCIException => err
|
323
|
+
raise_dbierror(err)
|
324
|
+
end
|
325
|
+
|
326
|
+
def execute
|
327
|
+
@cursor.exec
|
328
|
+
rescue OCIException => err
|
329
|
+
raise_dbierror(err)
|
330
|
+
end
|
331
|
+
|
332
|
+
def finish
|
333
|
+
@cursor.close
|
334
|
+
rescue OCIException => err
|
335
|
+
raise_dbierror(err)
|
336
|
+
end
|
337
|
+
|
338
|
+
def fetch
|
339
|
+
@cursor.fetch
|
340
|
+
rescue OCIException => err
|
341
|
+
raise_dbierror(err)
|
342
|
+
end
|
343
|
+
|
344
|
+
def column_info
|
345
|
+
# minimum implementation.
|
346
|
+
@cursor.column_metadata.collect do |md|
|
347
|
+
col = column_metadata_to_column_info(md)
|
348
|
+
col['indexed'] = nil
|
349
|
+
col['primary'] = nil
|
350
|
+
col['unique'] = nil
|
351
|
+
col['default'] = nil
|
352
|
+
col
|
353
|
+
end
|
354
|
+
rescue OCIException => err
|
355
|
+
raise_dbierror(err)
|
356
|
+
end
|
357
|
+
|
358
|
+
def rows
|
359
|
+
@cursor.row_count
|
360
|
+
rescue OCIException => err
|
361
|
+
raise_dbierror(err)
|
362
|
+
end
|
363
|
+
|
364
|
+
def __rowid
|
365
|
+
@cursor.rowid
|
366
|
+
end
|
367
|
+
|
368
|
+
def __define(pos, type, length = nil)
|
369
|
+
@cursor.define(pos, type, length)
|
370
|
+
self
|
371
|
+
end
|
372
|
+
|
373
|
+
def __bind_value(param)
|
374
|
+
@cursor[param]
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
if defined? ::OCI8::BindType::Base
|
379
|
+
##
|
380
|
+
## ruby-oci8 2.0 bind classes.
|
381
|
+
##
|
382
|
+
|
383
|
+
module BindType # :nodoc:
|
384
|
+
|
385
|
+
# helper class to define/bind DBI::Date.
|
386
|
+
class DBIDate < ::OCI8::BindType::OraDate
|
387
|
+
def set(val)
|
388
|
+
# convert val to an OraDate,
|
389
|
+
# then set it to the bind handle.
|
390
|
+
super(val && OraDate.new(val.year, val.month, val.day))
|
391
|
+
end
|
392
|
+
def get()
|
393
|
+
# get an Oradate from the bind handle,
|
394
|
+
# then convert it to a DBI::Date.
|
395
|
+
val = super()
|
396
|
+
return nil if val.nil?
|
397
|
+
DBI::Date.new(val.year, val.month, val.day)
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
# helper class to define/bind DBI::Timestamp.
|
402
|
+
#
|
403
|
+
# To fetch all Oracle's DATE columns as DBI::Timestamp:
|
404
|
+
# ::OCI8::BindType::Mapping[OCI8::SQLT_DAT] = ::DBI::DBD::OCI8::BindType::DBITimestamp
|
405
|
+
#
|
406
|
+
class DBITimestamp < ::OCI8::BindType::OraDate
|
407
|
+
def set(val)
|
408
|
+
# convert val to an OraDate,
|
409
|
+
# then set it to the bind handle.
|
410
|
+
super(val && OraDate.new(val.year, val.month, val.day,
|
411
|
+
val.respond_to?(:hour) ? val.hour : 0,
|
412
|
+
val.respond_to?(:min) ? val.min : 0,
|
413
|
+
val.respond_to?(:sec) ? val.sec : 0))
|
414
|
+
end
|
415
|
+
def get()
|
416
|
+
# get an Oradate from the bind handle,
|
417
|
+
# then convert it to a DBI::Timestamp.
|
418
|
+
val = super()
|
419
|
+
return nil if val.nil?
|
420
|
+
DBI::Timestamp.new(val.year, val.month, val.day, val.hour, val.minute, val.second)
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
# helper class to bind ref cursor as DBI::StatementHandle.
|
425
|
+
#
|
426
|
+
# # Create package
|
427
|
+
# dbh.execute(<<EOS)
|
428
|
+
# create or replace package test_pkg is
|
429
|
+
# type ref_cursor is ref cursor;
|
430
|
+
# procedure tab_table(csr out ref_cursor);
|
431
|
+
# end;
|
432
|
+
# EOS
|
433
|
+
#
|
434
|
+
# # Create package body
|
435
|
+
# dbh.execute(<<EOS)
|
436
|
+
# create or replace package body test_pkg is
|
437
|
+
# procedure tab_table(csr out ref_cursor) is
|
438
|
+
# begin
|
439
|
+
# open csr for select * from tab;
|
440
|
+
# end;
|
441
|
+
# end;
|
442
|
+
# EOS
|
443
|
+
#
|
444
|
+
# # Execute test_pkg.tab_table.
|
445
|
+
# # The first parameter is bound as DBI::StatementHandle.
|
446
|
+
# plsql = dbh.execute("begin test_pkg.tab_table(?); end;", DBI::StatementHandle)
|
447
|
+
#
|
448
|
+
# # Get the first parameter, which is a DBI::StatementHandle.
|
449
|
+
# sth = plsql.func(:bind_value, 1)
|
450
|
+
#
|
451
|
+
# # fetch column data.
|
452
|
+
# sth.fetch_all
|
453
|
+
#
|
454
|
+
class DBIStatementHandle < ::OCI8::BindType::Cursor
|
455
|
+
def set(val)
|
456
|
+
if val.is_a? DBI::StatementHandle
|
457
|
+
# get OCI8::Cursor
|
458
|
+
val = val.instance_eval do @handle end
|
459
|
+
val = val.instance_eval do @cursor end
|
460
|
+
end
|
461
|
+
super(val)
|
462
|
+
end
|
463
|
+
def get()
|
464
|
+
val = super
|
465
|
+
return nil if val.nil?
|
466
|
+
stmt = DBI::DBD::OCI8::Statement.new(val)
|
467
|
+
DBI::StatementHandle.new(stmt, true, false)
|
468
|
+
end
|
469
|
+
end
|
470
|
+
end # BindType
|
471
|
+
|
472
|
+
else
|
473
|
+
##
|
474
|
+
## ruby-oci8 1.0 bind classes.
|
475
|
+
##
|
476
|
+
|
477
|
+
module BindType # :nodoc:
|
478
|
+
DBIDate = Object.new
|
479
|
+
class << DBIDate
|
480
|
+
def fix_type(env, val, length, precision, scale)
|
481
|
+
# bind as an OraDate
|
482
|
+
[::OCI8::SQLT_DAT, val, nil]
|
483
|
+
end
|
484
|
+
def decorate(b)
|
485
|
+
def b.set(val)
|
486
|
+
# convert val to an OraDate,
|
487
|
+
# then set it to the bind handle.
|
488
|
+
super(val && OraDate.new(val.year, val.month, val.day))
|
489
|
+
end
|
490
|
+
def b.get()
|
491
|
+
# get an Oradate from the bind handle,
|
492
|
+
# then convert it to a DBI::Date.
|
493
|
+
(val = super()) && DBI::Date.new(val.year, val.month, val.day)
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
DBITimestamp = Object.new
|
499
|
+
class << DBITimestamp
|
500
|
+
def fix_type(env, val, length, precision, scale)
|
501
|
+
# bind as an OraDate
|
502
|
+
[::OCI8::SQLT_DAT, val, nil]
|
503
|
+
end
|
504
|
+
def decorate(b)
|
505
|
+
def b.set(val)
|
506
|
+
# convert val to an OraDate,
|
507
|
+
# then set it to the bind handle.
|
508
|
+
super(val && OraDate.new(val.year, val.month, val.day,
|
509
|
+
val.respond_to?(:hour) ? val.hour : 0,
|
510
|
+
val.respond_to?(:min) ? val.min : 0,
|
511
|
+
val.respond_to?(:sec) ? val.sec : 0))
|
512
|
+
end
|
513
|
+
def b.get()
|
514
|
+
# get an Oradate from the bind handle,
|
515
|
+
# then convert it to a DBI::Timestamp.
|
516
|
+
(val = super()) && DBI::Timestamp.new(val.year, val.month, val.day, val.hour, val.minute, val.second)
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
521
|
+
DBIStatementHandle = Object.new
|
522
|
+
class << DBIStatementHandle
|
523
|
+
def fix_type(env, val, length, precision, scale)
|
524
|
+
raise NotImplementedError unless val.nil?
|
525
|
+
[::OCI8::SQLT_RSET, nil, env.alloc(OCIStmt)]
|
526
|
+
end
|
527
|
+
def decorate(b)
|
528
|
+
def b.set(val)
|
529
|
+
raise NotImplementedError
|
530
|
+
end
|
531
|
+
def b.get()
|
532
|
+
val = super
|
533
|
+
return val if val.nil?
|
534
|
+
cur = ::OCI8::Cursor.new(@env, @svc, @ctx, val)
|
535
|
+
stmt = DBI::DBD::OCI8::Statement.new(cur)
|
536
|
+
DBI::StatementHandle.new(stmt, true, false)
|
537
|
+
end
|
538
|
+
end
|
539
|
+
end
|
540
|
+
end # BindType
|
541
|
+
end
|
542
|
+
|
543
|
+
::OCI8::BindType::Mapping[DBI::Date] = BindType::DBIDate
|
544
|
+
::OCI8::BindType::Mapping[DBI::Timestamp] = BindType::DBITimestamp
|
545
|
+
::OCI8::BindType::Mapping[DBI::StatementHandle] = BindType::DBIStatementHandle
|
546
|
+
|
547
|
+
end # module OCI8
|
548
|
+
end # module DBD
|
549
|
+
end # module DBI
|