ruby-oci8 2.0.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/ChangeLog +1912 -0
  2. data/Makefile +96 -0
  3. data/NEWS +223 -0
  4. data/README +86 -0
  5. data/VERSION +1 -0
  6. data/dist-files +77 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/lib/.document +1 -0
  13. data/lib/dbd/OCI8.rb +591 -0
  14. data/lib/oci8.rb +82 -0
  15. data/lib/oci8.rb.in +82 -0
  16. data/lib/oci8/.document +5 -0
  17. data/lib/oci8/bindtype.rb +319 -0
  18. data/lib/oci8/compat.rb +113 -0
  19. data/lib/oci8/datetime.rb +619 -0
  20. data/lib/oci8/encoding-init.rb +40 -0
  21. data/lib/oci8/encoding.yml +537 -0
  22. data/lib/oci8/metadata.rb +2077 -0
  23. data/lib/oci8/object.rb +562 -0
  24. data/lib/oci8/oci8.rb +571 -0
  25. data/lib/oci8/oracle_version.rb +144 -0
  26. data/lib/oci8lib_18.so +0 -0
  27. data/lib/oci8lib_191.so +0 -0
  28. data/metaconfig +142 -0
  29. data/pre-distclean.rb +7 -0
  30. data/ruby-oci8.gemspec +63 -0
  31. data/setup.rb +1331 -0
  32. data/test/README +4 -0
  33. data/test/config.rb +109 -0
  34. data/test/test_all.rb +50 -0
  35. data/test/test_appinfo.rb +63 -0
  36. data/test/test_array_dml.rb +333 -0
  37. data/test/test_bind_raw.rb +46 -0
  38. data/test/test_bind_time.rb +178 -0
  39. data/test/test_break.rb +83 -0
  40. data/test/test_clob.rb +79 -0
  41. data/test/test_connstr.rb +81 -0
  42. data/test/test_datetime.rb +622 -0
  43. data/test/test_dbi.rb +366 -0
  44. data/test/test_dbi_clob.rb +53 -0
  45. data/test/test_encoding.rb +100 -0
  46. data/test/test_metadata.rb +257 -0
  47. data/test/test_oci8.rb +434 -0
  48. data/test/test_oracle_version.rb +70 -0
  49. data/test/test_oradate.rb +256 -0
  50. data/test/test_oranumber.rb +655 -0
  51. data/test/test_rowid.rb +33 -0
  52. metadata +108 -0
@@ -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
+ }
@@ -0,0 +1 @@
1
+ oci8
@@ -0,0 +1,591 @@
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.4"
46
+
47
+ def self.driver_name
48
+ "OCI8"
49
+ end
50
+
51
+ # type converstion handler to bind values. (ruby-dbi 0.4)
52
+ if DBI.const_defined?(:TypeUtil)
53
+ DBI::TypeUtil.register_conversion("OCI8") do |obj|
54
+ case obj
55
+ when ::TrueClass
56
+ ['1', false]
57
+ when ::FalseClass
58
+ ['0', false]
59
+ else
60
+ [obj, false]
61
+ end
62
+ end
63
+ end
64
+
65
+ # no type converstion is required for result set. (ruby-dbi 0.4)
66
+ class NoTypeConversion
67
+ def self.parse(obj)
68
+ obj
69
+ end
70
+ end
71
+
72
+ module Util
73
+
74
+ ERROR_MAP = {
75
+ 1 => DBI::IntegrityError, # unique constraint violated
76
+ 900 => DBI::ProgrammingError, # invalid SQL statement
77
+ 904 => DBI::ProgrammingError, # invalid identifier
78
+ 905 => DBI::ProgrammingError, # missing keyword
79
+ 923 => DBI::ProgrammingError, # FROM keyword not found where expected
80
+ 936 => DBI::ProgrammingError, # missing expression
81
+ 942 => DBI::ProgrammingError, # table or view does not exist
82
+ 2290 => DBI::IntegrityError, # check constraint violated
83
+ 2291 => DBI::IntegrityError, # parent key not found
84
+ 2292 => DBI::IntegrityError, # child record found
85
+ 2293 => DBI::IntegrityError, # check constraint violated
86
+ }
87
+
88
+ def raise_dbierror(err) # :nodoc:
89
+ if err.is_a? OCIError
90
+ exc = ERROR_MAP[err.code] || DBI::DatabaseError
91
+ raise exc.new(err.message, err.code)
92
+ else
93
+ raise DBI::DatabaseError.new(err.message, -1)
94
+ end
95
+ rescue DBI::DatabaseError => exc
96
+ exc.set_backtrace(err.backtrace)
97
+ raise
98
+ end
99
+
100
+ def column_metadata_to_column_info(col)
101
+ sql_type, type_name, precision, scale =
102
+ case col.data_type
103
+ when :char
104
+ [SQL_CHAR, col.charset_form == :nchar ? "NCHAR" : "CHAR", col.data_size, nil]
105
+ when :varchar2
106
+ [SQL_VARCHAR, col.charset_form == :nchar ? "NVARCHAR2" : "VARCHAR2", col.data_size, nil]
107
+ when :raw
108
+ [SQL_VARBINARY, "RAW", col.data_size, nil]
109
+ when :long
110
+ [SQL_LONGVARCHAR, "LONG", 4000, nil]
111
+ when :long_raw
112
+ [SQL_LONGVARBINARY, "LONG RAW", 4000, nil]
113
+ when :clob
114
+ [SQL_CLOB, col.charset_form == :nchar ? "NCLOB" : "CLOB", 4000, nil]
115
+ when :blob
116
+ [SQL_BLOB, "BLOB", 4000, nil]
117
+ when :bfile
118
+ [SQL_BLOB, "BFILE", 4000, nil]
119
+ when :number
120
+ if col.scale == -127 && col.precision != 0
121
+ # To convert from binary to decimal precision, multiply n by 0.30103.
122
+ [SQL_FLOAT, "FLOAT", (col.precision * 0.30103).ceil , nil]
123
+ elsif col.precision == 0
124
+ # NUMBER or calculated value (eg. col * 1.2).
125
+ [SQL_NUMERIC, "NUMBER", 38, nil]
126
+ else
127
+ [SQL_NUMERIC, "NUMBER", col.precision, col.scale]
128
+ end
129
+ when :binary_float
130
+ # (23 * 0.30103).ceil => 7
131
+ [SQL_FLOAT, "BINARY_FLOAT", 7, nil]
132
+ when :binary_double
133
+ # (52 * 0.30103).ceil => 16
134
+ [SQL_DOUBLE, "BINARY_DOUBLE", 16, nil]
135
+ when :date
136
+ # yyyy-mm-dd hh:mi:ss
137
+ [SQL_DATE, "DATE", 19, nil]
138
+ when :timestamp
139
+ # yyyy-mm-dd hh:mi:ss.SSSS
140
+ [SQL_TIMESTAMP, "TIMESTAMP", 20 + col.fsprecision, nil]
141
+ when :timestamp_tz
142
+ # yyyy-mm-dd hh:mi:ss.SSSS +HH:MM
143
+ [SQL_TIMESTAMP, "TIMESTAMP WITH TIME ZONE", 27 + col.fsprecision, nil]
144
+ when :timestamp_ltz
145
+ # yyyy-mm-dd hh:mi:ss.SSSS
146
+ [SQL_TIMESTAMP, "TIMESTAMP WITH LOCAL TIME ZONE", 20 + col.fsprecision, nil]
147
+ when :interval_ym
148
+ # yyyy-mm
149
+ [SQL_OTHER, 'INTERVAL YEAR TO MONTH', col.lfprecision + 3, nil]
150
+ when :interval_ds
151
+ # dd hh:mi:ss.SSSSS
152
+ [SQL_OTHER, 'INTERVAL DAY TO SECOND', col.lfprecision + 10 + col.fsprecision, nil]
153
+ else
154
+ [SQL_OTHER, col.data_type.to_s, nil, nil]
155
+ end
156
+ {'name' => col.name,
157
+ 'sql_type' => sql_type,
158
+ 'type_name' => type_name,
159
+ 'nullable' => col.nullable?,
160
+ 'precision' => precision,
161
+ 'scale' => scale,
162
+ 'dbi_type' => NoTypeConversion,
163
+ }
164
+ end
165
+ private :column_metadata_to_column_info
166
+ end
167
+
168
+ class Driver < DBI::BaseDriver # :nodoc:
169
+ include Util
170
+
171
+ def initialize
172
+ super(USED_DBD_VERSION)
173
+ end
174
+
175
+ # external OS authentication
176
+ # (contributed by Dan Fitch)
177
+ def default_user
178
+ [nil, nil]
179
+ end
180
+
181
+ def connect( dbname, user, auth, attr )
182
+ handle = ::OCI8.new(user, auth, dbname, attr['Privilege'])
183
+ handle.non_blocking = true if attr['NonBlocking']
184
+ return Database.new(handle, attr)
185
+ rescue OCIException => err
186
+ raise_dbierror(err)
187
+ end
188
+ end
189
+
190
+ class Database < DBI::BaseDatabase
191
+ include Util
192
+
193
+ def disconnect
194
+ @handle.logoff
195
+ rescue OCIException => err
196
+ raise_dbierror(err)
197
+ end
198
+
199
+ def prepare( statement )
200
+ # convert ?-style parameters to :1, :2 etc.
201
+ prep_statement = DBI::SQL::PreparedStatement.new(DummyQuoter.new, statement)
202
+ if prep_statement.unbound.size > 0
203
+ arr = (1..(prep_statement.unbound.size)).collect{|i| ":#{i}"}
204
+ statement = prep_statement.bind( arr )
205
+ end
206
+ cursor = @handle.parse(statement)
207
+ Statement.new(cursor)
208
+ rescue OCIException => err
209
+ raise_dbierror(err)
210
+ end
211
+
212
+ def ping
213
+ @handle.exec("BEGIN NULL; END;")
214
+ true
215
+ rescue
216
+ false
217
+ end
218
+
219
+ def commit
220
+ @handle.commit()
221
+ rescue OCIException => err
222
+ raise_dbierror(err)
223
+ end
224
+
225
+ def rollback
226
+ @handle.rollback()
227
+ rescue OCIException => err
228
+ raise_dbierror(err)
229
+ end
230
+
231
+ def tables
232
+ stmt = execute("SELECT object_name FROM user_objects where object_type in ('TABLE', 'VIEW')")
233
+ rows = stmt.fetch_all || []
234
+ stmt.finish
235
+ rows.collect {|row| row[0]}
236
+ end
237
+
238
+ # SQLs are copied from DBD::Oracle.
239
+ def columns(table)
240
+ tab = @handle.describe_table(table)
241
+ cols = tab.columns
242
+ cols.collect! do |col|
243
+ column_metadata_to_column_info(col)
244
+ end
245
+
246
+ dbh = DBI::DatabaseHandle.new(self)
247
+
248
+ primaries = {}
249
+ dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name) do |row|
250
+ select column_name
251
+ from all_cons_columns a, all_constraints b
252
+ where a.owner = b.owner
253
+ and a.constraint_name = b.constraint_name
254
+ and a.table_name = b.table_name
255
+ and b.constraint_type = 'P'
256
+ and b.owner = :1
257
+ and b.table_name = :2
258
+ EOS
259
+ primaries[row[0]] = true
260
+ end
261
+
262
+ indices = {}
263
+ uniques = {}
264
+ dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name) do |row|
265
+ select a.column_name, a.index_name, b.uniqueness
266
+ from all_ind_columns a, all_indexes b
267
+ where a.index_name = b.index_name
268
+ and a.index_owner = b.owner
269
+ and a.table_owner = :1
270
+ and a.table_name = :2
271
+ EOS
272
+ col_name, index_name, uniqueness = row
273
+ indices[col_name] = true
274
+ uniques[col_name] = true if uniqueness == 'UNIQUE'
275
+ end
276
+
277
+ dbh.select_all(<<EOS, tab.obj_schema, tab.obj_name).collect do |row|
278
+ select column_id, column_name, data_default
279
+ from all_tab_columns
280
+ where owner = :1
281
+ and table_name = :2
282
+ EOS
283
+ col_id, col_name, default = row
284
+
285
+ col = cols[col_id.to_i - 1]
286
+ col_name = col['name']
287
+
288
+ if default && default[0] == ?'
289
+ default = default[1..-2].gsub(/''/, "'")
290
+ end
291
+
292
+ col['indexed'] = indices[col_name] || false
293
+ col['primary'] = primaries[col_name] || false
294
+ col['unique'] = uniques[col_name] || false
295
+ col['default'] = default
296
+ col
297
+ end
298
+ rescue OCIException => err
299
+ raise_dbierror(err)
300
+ end
301
+
302
+ def [](attr)
303
+ case attr
304
+ when 'AutoCommit'
305
+ @handle.autocommit?
306
+ end
307
+ end
308
+
309
+ def []=(attr, value)
310
+ case attr
311
+ when 'AutoCommit'
312
+ @handle.autocommit = value
313
+ end
314
+ end
315
+
316
+ private
317
+
318
+ class DummyQuoter # :nodoc:
319
+ # dummy to substitute ?-style parameter markers by :1 :2 etc.
320
+ def quote(str)
321
+ str
322
+ end
323
+ end
324
+ end
325
+
326
+ class Statement < DBI::BaseStatement
327
+ include Util
328
+
329
+ def initialize(cursor)
330
+ @cursor = cursor
331
+ end
332
+
333
+ def bind_param( param, value, attribs)
334
+ if attribs.nil? || attribs['type'].nil?
335
+ if value.nil?
336
+ @cursor.bind_param(param, nil, String, 1)
337
+ else
338
+ @cursor.bind_param(param, value)
339
+ end
340
+ else
341
+ case attribs['type']
342
+ when SQL_BINARY
343
+ type = OCI_TYPECODE_RAW
344
+ else
345
+ type = attribs['type']
346
+ end
347
+ @cursor.bind_param(param, value, type)
348
+ end
349
+ rescue OCIException => err
350
+ raise_dbierror(err)
351
+ end
352
+
353
+ def execute
354
+ @cursor.exec
355
+ rescue OCIException => err
356
+ raise_dbierror(err)
357
+ end
358
+
359
+ def finish
360
+ @cursor.close
361
+ rescue OCIException => err
362
+ raise_dbierror(err)
363
+ end
364
+
365
+ def fetch
366
+ @cursor.fetch
367
+ rescue OCIException => err
368
+ raise_dbierror(err)
369
+ end
370
+
371
+ def column_info
372
+ # minimum implementation.
373
+ @cursor.column_metadata.collect do |md|
374
+ col = column_metadata_to_column_info(md)
375
+ col['indexed'] = nil
376
+ col['primary'] = nil
377
+ col['unique'] = nil
378
+ col['default'] = nil
379
+ col
380
+ end
381
+ rescue OCIException => err
382
+ raise_dbierror(err)
383
+ end
384
+
385
+ def rows
386
+ @cursor.row_count
387
+ rescue OCIException => err
388
+ raise_dbierror(err)
389
+ end
390
+
391
+ def __rowid
392
+ @cursor.rowid
393
+ end
394
+
395
+ def __define(pos, type, length = nil)
396
+ @cursor.define(pos, type, length)
397
+ self
398
+ end
399
+
400
+ def __bind_value(param)
401
+ @cursor[param]
402
+ end
403
+ end
404
+
405
+ # DBI_STMT_NEW_ARGS is DBI::StatementHandle.new's arguments except +handle+.
406
+ #
407
+ # FYI: DBI::StatementHandle.new method signatures are follows:
408
+ # 0.2.2: handle, fetchable=false, prepared=true
409
+ # 0.4.0: handle, fetchable=false, prepared=true, convert_types=true
410
+ # 0.4.1: handle, fetchable=false, prepared=true, convert_types=true, executed=false
411
+ begin
412
+ DBI::StatementHandle.new(nil, false, true, true, true)
413
+ # dbi 0.4.1
414
+ DBI_STMT_NEW_ARGS = [true, true, true, true] # :nodoc:
415
+ rescue ArgumentError
416
+ # dbi 0.4.0 or lower
417
+ DBI_STMT_NEW_ARGS = [true] # :nodoc:
418
+ end
419
+
420
+ if defined? ::OCI8::BindType::Base
421
+ ##
422
+ ## ruby-oci8 2.0 bind classes.
423
+ ##
424
+
425
+ module BindType # :nodoc:
426
+
427
+ # helper class to define/bind DBI::Date.
428
+ class DBIDate < ::OCI8::BindType::OraDate
429
+ def set(val)
430
+ # convert val to an OraDate,
431
+ # then set it to the bind handle.
432
+ super(val && OraDate.new(val.year, val.month, val.day))
433
+ end
434
+ def get()
435
+ # get an Oradate from the bind handle,
436
+ # then convert it to a DBI::Date.
437
+ val = super()
438
+ return nil if val.nil?
439
+ DBI::Date.new(val.year, val.month, val.day)
440
+ end
441
+ end
442
+
443
+ # helper class to define/bind DBI::Timestamp.
444
+ #
445
+ # To fetch all Oracle's DATE columns as DBI::Timestamp:
446
+ # ::OCI8::BindType::Mapping[OCI8::SQLT_DAT] = ::DBI::DBD::OCI8::BindType::DBITimestamp
447
+ #
448
+ class DBITimestamp < ::OCI8::BindType::OraDate
449
+ def set(val)
450
+ # convert val to an OraDate,
451
+ # then set it to the bind handle.
452
+ super(val && OraDate.new(val.year, val.month, val.day,
453
+ val.respond_to?(:hour) ? val.hour : 0,
454
+ val.respond_to?(:min) ? val.min : 0,
455
+ val.respond_to?(:sec) ? val.sec : 0))
456
+ end
457
+ def get()
458
+ # get an Oradate from the bind handle,
459
+ # then convert it to a DBI::Timestamp.
460
+ val = super()
461
+ return nil if val.nil?
462
+ DBI::Timestamp.new(val.year, val.month, val.day, val.hour, val.minute, val.second)
463
+ end
464
+ end
465
+
466
+ # helper class to bind ref cursor as DBI::StatementHandle.
467
+ #
468
+ # # Create package
469
+ # dbh.execute(<<EOS)
470
+ # create or replace package test_pkg is
471
+ # type ref_cursor is ref cursor;
472
+ # procedure tab_table(csr out ref_cursor);
473
+ # end;
474
+ # EOS
475
+ #
476
+ # # Create package body
477
+ # dbh.execute(<<EOS)
478
+ # create or replace package body test_pkg is
479
+ # procedure tab_table(csr out ref_cursor) is
480
+ # begin
481
+ # open csr for select * from tab;
482
+ # end;
483
+ # end;
484
+ # EOS
485
+ #
486
+ # # Execute test_pkg.tab_table.
487
+ # # The first parameter is bound as DBI::StatementHandle.
488
+ # plsql = dbh.execute("begin test_pkg.tab_table(?); end;", DBI::StatementHandle)
489
+ #
490
+ # # Get the first parameter, which is a DBI::StatementHandle.
491
+ # sth = plsql.func(:bind_value, 1)
492
+ #
493
+ # # fetch column data.
494
+ # sth.fetch_all
495
+ #
496
+ class DBIStatementHandle < ::OCI8::BindType::Cursor
497
+ def set(val)
498
+ if val.is_a? DBI::StatementHandle
499
+ # get OCI8::Cursor
500
+ val = val.instance_eval do @handle end
501
+ val = val.instance_eval do @cursor end
502
+ end
503
+ super(val)
504
+ end
505
+ def get()
506
+ val = super
507
+ return nil if val.nil?
508
+ stmt = DBI::DBD::OCI8::Statement.new(val)
509
+ DBI::StatementHandle.new(stmt, *DBI_STMT_NEW_ARGS)
510
+ end
511
+ end
512
+ end # BindType
513
+
514
+ else
515
+ ##
516
+ ## ruby-oci8 1.0 bind classes.
517
+ ##
518
+
519
+ module BindType # :nodoc:
520
+ DBIDate = Object.new
521
+ class << DBIDate
522
+ def fix_type(env, val, length, precision, scale)
523
+ # bind as an OraDate
524
+ [::OCI8::SQLT_DAT, val, nil]
525
+ end
526
+ def decorate(b)
527
+ def b.set(val)
528
+ # convert val to an OraDate,
529
+ # then set it to the bind handle.
530
+ super(val && OraDate.new(val.year, val.month, val.day))
531
+ end
532
+ def b.get()
533
+ # get an Oradate from the bind handle,
534
+ # then convert it to a DBI::Date.
535
+ (val = super()) && DBI::Date.new(val.year, val.month, val.day)
536
+ end
537
+ end
538
+ end
539
+
540
+ DBITimestamp = Object.new
541
+ class << DBITimestamp
542
+ def fix_type(env, val, length, precision, scale)
543
+ # bind as an OraDate
544
+ [::OCI8::SQLT_DAT, val, nil]
545
+ end
546
+ def decorate(b)
547
+ def b.set(val)
548
+ # convert val to an OraDate,
549
+ # then set it to the bind handle.
550
+ super(val && OraDate.new(val.year, val.month, val.day,
551
+ val.respond_to?(:hour) ? val.hour : 0,
552
+ val.respond_to?(:min) ? val.min : 0,
553
+ val.respond_to?(:sec) ? val.sec : 0))
554
+ end
555
+ def b.get()
556
+ # get an Oradate from the bind handle,
557
+ # then convert it to a DBI::Timestamp.
558
+ (val = super()) && DBI::Timestamp.new(val.year, val.month, val.day, val.hour, val.minute, val.second)
559
+ end
560
+ end
561
+ end
562
+
563
+ DBIStatementHandle = Object.new
564
+ class << DBIStatementHandle
565
+ def fix_type(env, val, length, precision, scale)
566
+ raise NotImplementedError unless val.nil?
567
+ [::OCI8::SQLT_RSET, nil, env.alloc(OCIStmt)]
568
+ end
569
+ def decorate(b)
570
+ def b.set(val)
571
+ raise NotImplementedError
572
+ end
573
+ def b.get()
574
+ val = super
575
+ return val if val.nil?
576
+ cur = ::OCI8::Cursor.new(@env, @svc, @ctx, val)
577
+ stmt = DBI::DBD::OCI8::Statement.new(cur)
578
+ DBI::StatementHandle.new(stmt, *DBI_STMT_NEW_ARGS)
579
+ end
580
+ end
581
+ end
582
+ end # BindType
583
+ end
584
+
585
+ ::OCI8::BindType::Mapping[DBI::Date] = BindType::DBIDate
586
+ ::OCI8::BindType::Mapping[DBI::Timestamp] = BindType::DBITimestamp
587
+ ::OCI8::BindType::Mapping[DBI::StatementHandle] = BindType::DBIStatementHandle
588
+
589
+ end # module OCI8
590
+ end # module DBD
591
+ end # module DBI