ruby-oci8 2.0.6 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/ChangeLog +366 -19
  2. data/Makefile +2 -8
  3. data/NEWS +111 -0
  4. data/README +4 -85
  5. data/VERSION +1 -1
  6. data/dist-files +9 -2
  7. data/ext/oci8/.document +1 -0
  8. data/ext/oci8/apiwrap.c.tmpl +12 -2
  9. data/ext/oci8/apiwrap.yml +37 -21
  10. data/ext/oci8/attr.c +23 -74
  11. data/ext/oci8/bind.c +93 -225
  12. data/ext/oci8/connection_pool.c +201 -0
  13. data/ext/oci8/encoding.c +117 -24
  14. data/ext/oci8/env.c +5 -10
  15. data/ext/oci8/error.c +171 -189
  16. data/ext/oci8/extconf.rb +6 -2
  17. data/ext/oci8/lob.c +81 -79
  18. data/ext/oci8/metadata.c +42 -177
  19. data/ext/oci8/object.c +55 -28
  20. data/ext/oci8/oci8.c +426 -294
  21. data/ext/oci8/oci8.h +84 -51
  22. data/ext/oci8/oci8lib.c +75 -53
  23. data/ext/oci8/ocidatetime.c +67 -88
  24. data/ext/oci8/ocihandle.c +78 -37
  25. data/ext/oci8/ocinumber.c +166 -109
  26. data/ext/oci8/oraconf.rb +68 -157
  27. data/ext/oci8/oradate.c +2 -7
  28. data/ext/oci8/stmt.c +40 -183
  29. data/ext/oci8/thread_util.c +85 -0
  30. data/ext/oci8/thread_util.h +30 -0
  31. data/lib/oci8.rb.in +19 -13
  32. data/lib/oci8/.document +2 -0
  33. data/lib/oci8/bindtype.rb +62 -45
  34. data/lib/oci8/connection_pool.rb +118 -0
  35. data/lib/oci8/datetime.rb +304 -320
  36. data/lib/oci8/encoding-init.rb +62 -30
  37. data/lib/oci8/encoding.yml +3 -3
  38. data/lib/oci8/metadata.rb +552 -497
  39. data/lib/oci8/object.rb +9 -9
  40. data/lib/oci8/oci8.rb +161 -2
  41. data/lib/oci8/ocihandle.rb +427 -0
  42. data/lib/oci8/properties.rb +31 -1
  43. data/ruby-oci8.gemspec +10 -3
  44. data/test/README +41 -3
  45. data/test/config.rb +16 -0
  46. data/test/test_all.rb +3 -0
  47. data/test/test_bind_string.rb +106 -0
  48. data/test/test_break.rb +33 -7
  49. data/test/test_clob.rb +13 -10
  50. data/test/test_connection_pool.rb +125 -0
  51. data/test/test_connstr.rb +2 -2
  52. data/test/test_datetime.rb +26 -66
  53. data/test/test_encoding.rb +7 -3
  54. data/test/test_error.rb +88 -0
  55. data/test/test_metadata.rb +1356 -204
  56. data/test/test_oci8.rb +27 -8
  57. data/test/test_oranumber.rb +41 -0
  58. metadata +34 -9
  59. data/ext/oci8/xmldb.c +0 -383
@@ -59,7 +59,7 @@ class OCI8
59
59
 
60
60
  private
61
61
 
62
- def datetime_to_array(val, full)
62
+ def datetime_to_array(val, datatype)
63
63
  return nil if val.nil?
64
64
 
65
65
  # year
@@ -98,7 +98,7 @@ class OCI8
98
98
  else
99
99
  sec = 0
100
100
  end
101
- return [year, month, day, hour, minute, sec] unless full
101
+ return [year, month, day, hour, minute, sec] if datatype == :date
102
102
 
103
103
  # fractional second
104
104
  if val.respond_to? :sec_fraction
@@ -110,6 +110,8 @@ class OCI8
110
110
  else
111
111
  fsec = 0
112
112
  end
113
+ return [year, month, day, hour, minute, sec, fsec, nil, nil] if datatype == :timestamp
114
+
113
115
  # time zone
114
116
  if val.respond_to? :offset
115
117
  # DateTime
@@ -134,147 +136,91 @@ class OCI8
134
136
  [year, month, day, hour, minute, sec, fsec, tz_hour, tz_min]
135
137
  end
136
138
 
137
- def ocidate_to_datetime(ary)
139
+ def array_to_datetime(ary, timezone)
138
140
  return nil if ary.nil?
139
141
 
140
- year, month, day, hour, minute, sec = ary
141
- if @@default_timezone == :local
142
- if ::DateTime.respond_to? :local_offset
143
- offset = ::DateTime.local_offset # Use a method defined by active support.
142
+ year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
143
+ sec += nsec.to_r / 1000000000 if nsec and nsec != 0
144
+ if tz_hour and tz_min
145
+ offset = tz_hour.to_r / 24 + tz_min.to_r / 1440
146
+ else
147
+ if @@default_timezone == :local
148
+ if ::DateTime.respond_to? :local_offset
149
+ offset = ::DateTime.local_offset # Use a method defined by active support.
150
+ else
151
+ # Do as active support does.
152
+ offset = ::Time.local(2007).utc_offset.to_r / 86400
153
+ end
144
154
  else
145
- # Do as active support does.
146
- offset = ::Time.local(2007).utc_offset.to_r / 86400
155
+ offset = 0
147
156
  end
148
- else
149
- offset = 0
150
157
  end
151
- ::DateTime.civil(year, month, day, hour, minute, sec, offset)
152
- end
153
158
 
154
- def ocidate_to_time(ary)
155
- return nil if ary.nil?
156
-
157
- year, month, day, hour, minute, sec = ary
158
- if @@time_new_accepts_timezone || year >= 139 || year < 0
159
- begin
160
- return ::Time.send(@@default_timezone, year, month, day, hour, minute, sec)
161
- rescue StandardError
159
+ if @@datetime_has_fractional_second_bug and sec >= 59 and nsec != 0
160
+ # convert to a DateTime via a String as a workaround
161
+ if offset >= 0
162
+ sign = ?+
163
+ else
164
+ sign = ?-
165
+ offset = - offset;
162
166
  end
167
+ tz_min = (offset * 1440).to_i
168
+ tz_hour, tz_min = tz_min.divmod 60
169
+ time_str = format("%04d-%02d-%02dT%02d:%02d:%02d.%09d%c%02d:%02d",
170
+ year, month, day, hour, minute, sec, nsec, sign, tz_hour, tz_min)
171
+ ::DateTime.parse(time_str)
172
+ else
173
+ ::DateTime.civil(year, month, day, hour, minute, sec, offset)
163
174
  end
164
- ocidate_to_datetime(ary)
165
175
  end
166
176
 
167
- if OCI8.oracle_client_version >= ORAVER_9_0
177
+ if @@time_new_accepts_timezone
168
178
 
169
- def ocitimestamp_to_datetime(ary)
179
+ # after ruby 1.9.2
180
+ def array_to_time(ary, timezone)
170
181
  return nil if ary.nil?
171
182
 
172
- year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
173
- if @@datetime_has_fractional_second_bug and sec >= 59 and fsec != 0
174
- # convert to a DateTime via a String as a workaround
175
- if tz_hour >= 0 && tz_min >= 0
176
- sign = ?+
177
- else
178
- sign = ?-
179
- tz_hour = - tz_hour
180
- tz_min = - tz_min
181
- end
182
- time_str = format("%04d-%02d-%02dT%02d:%02d:%02d.%09d%c%02d:%02d",
183
- year, month, day, hour, minute, sec, fsec, sign, tz_hour, tz_min)
184
- ::DateTime.parse(time_str)
183
+ year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
184
+ nsec ||= 0
185
+
186
+ if timezone
187
+ usec = (nsec == 0) ? 0 : nsec.to_r / 1000
188
+ ::Time.send(timezone, year, month, day, hour, minute, sec, usec)
185
189
  else
186
- sec += fsec.to_r / 1000000000
187
- offset = tz_hour.to_r / 24 + tz_min.to_r / 1440
188
- ::DateTime.civil(year, month, day, hour, minute, sec, offset)
190
+ sec += nsec.to_r / 1_000_000_000 if nsec != 0
191
+ utc_offset = tz_hour * 3600 + tz_min * 60
192
+ ::Time.new(year, month, day, hour, minute, sec, utc_offset)
189
193
  end
190
194
  end
191
195
 
192
- if @@time_new_accepts_timezone
193
-
194
- # after ruby 1.9.2
195
- def ocitimestamp_to_time(ary)
196
- return nil if ary.nil?
197
-
198
- year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
199
-
200
- sec += fsec / Rational(1000000000)
201
- utc_offset = tz_hour * 3600 + tz_min * 60
202
- return ::Time.new(year, month, day, hour, minute, sec, utc_offset)
203
- end
196
+ else
204
197
 
205
- else
198
+ # prior to ruby 1.9.2
199
+ def array_to_time(ary, timezone)
200
+ return nil if ary.nil?
206
201
 
207
- # prior to ruby 1.9.2
208
- def ocitimestamp_to_time(ary)
209
- return nil if ary.nil?
210
-
211
- year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
212
-
213
- if year >= 139 || year < 0
214
- begin
215
- if tz_hour == 0 and tz_min == 0
216
- return ::Time.utc(year, month, day, hour, minute, sec, fsec / Rational(1000))
217
- else
218
- tm = ::Time.local(year, month, day, hour, minute, sec, fsec / Rational(1000))
219
- return tm if tm.utc_offset == tz_hour * 3600 + tz_min * 60
220
- end
221
- rescue StandardError
202
+ year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
203
+ nsec ||= 0
204
+ usec = (nsec == 0) ? 0 : nsec.to_r / 1000
205
+ begin
206
+ if timezone
207
+ return ::Time.send(:timezone, year, month, day, hour, minute, sec, usec)
208
+ else
209
+ if tz_hour == 0 and tz_min == 0
210
+ tm = ::Time.utc(year, month, day, hour, minute, sec, usec)
211
+ # Time.utc(99, ...) returns a time object the year of which is 1999.
212
+ # 'tm.year == year' checks such cases.
213
+ return tm if tm.year == year
214
+ else
215
+ tm = ::Time.local(year, month, day, hour, minute, sec, usec)
216
+ return tm if tm.utc_offset == tz_hour * 3600 + tz_min * 60 and tm.year == year
222
217
  end
223
218
  end
224
- ocitimestamp_to_datetime(ary)
219
+ rescue StandardError
225
220
  end
226
-
227
- end
228
- end
229
- end
230
-
231
- class DateTimeViaOCIDate < OCI8::BindType::OCIDate # :nodoc:
232
- include OCI8::BindType::Util
233
-
234
- def set(val) # :nodoc:
235
- super(datetime_to_array(val, false))
236
- end
237
-
238
- def get() # :nodoc:
239
- ocidate_to_datetime(super())
240
- end
241
- end
242
-
243
- class TimeViaOCIDate < OCI8::BindType::OCIDate # :nodoc:
244
- include OCI8::BindType::Util
245
-
246
- def set(val) # :nodoc:
247
- super(datetime_to_array(val, false))
248
- end
249
-
250
- def get() # :nodoc:
251
- ocidate_to_time(super())
252
- end
253
- end
254
-
255
- if OCI8.oracle_client_version >= ORAVER_9_0
256
- class DateTimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
257
- include OCI8::BindType::Util
258
-
259
- def set(val) # :nodoc:
260
- super(datetime_to_array(val, true))
221
+ array_to_datetime(ary, timezone)
261
222
  end
262
223
 
263
- def get() # :nodoc:
264
- ocitimestamp_to_datetime(super())
265
- end
266
- end
267
-
268
- class TimeViaOCITimestampTZ < OCI8::BindType::OCITimestampTZ # :nodoc:
269
- include OCI8::BindType::Util
270
-
271
- def set(val) # :nodoc:
272
- super(datetime_to_array(val, true))
273
- end
274
-
275
- def get() # :nodoc:
276
- ocitimestamp_to_time(super())
277
- end
278
224
  end
279
225
  end
280
226
 
@@ -339,19 +285,39 @@ class OCI8
339
285
  # If you are in the regions where daylight saving time is adopted,
340
286
  # you should use OCI8::BindType::Time.
341
287
  #
342
- class DateTime
343
- if OCI8.oracle_client_version >= ORAVER_9_0
344
- def self.create(con, val, param, max_array_size) # :nodoc:
345
- if true # TODO: check Oracle server version
346
- DateTimeViaOCITimestampTZ.new(con, val, param, max_array_size)
347
- else
348
- DateTimeViaOCIDate.new(con, val, param, max_array_size)
349
- end
350
- end
351
- else
352
- def self.create(con, val, param, max_array_size) # :nodoc:
353
- DateTimeViaOCIDate.new(con, val, param, max_array_size)
354
- end
288
+ class DateTime < OCI8::BindType::OCITimestampTZ
289
+ include OCI8::BindType::Util
290
+
291
+ def set(val) # :nodoc:
292
+ super(datetime_to_array(val, :timestamp_tz))
293
+ end
294
+
295
+ def get() # :nodoc:
296
+ array_to_datetime(super(), nil)
297
+ end
298
+ end
299
+
300
+ class LocalDateTime < OCI8::BindType::OCITimestamp
301
+ include OCI8::BindType::Util
302
+
303
+ def set(val) # :nodoc:
304
+ super(datetime_to_array(val, :timestamp))
305
+ end
306
+
307
+ def get() # :nodoc:
308
+ array_to_datetime(super(), :local)
309
+ end
310
+ end
311
+
312
+ class UTCDateTime < OCI8::BindType::OCITimestamp
313
+ include OCI8::BindType::Util
314
+
315
+ def set(val) # :nodoc:
316
+ super(datetime_to_array(val, :timestamp))
317
+ end
318
+
319
+ def get() # :nodoc:
320
+ array_to_datetime(super(), :utc)
355
321
  end
356
322
  end
357
323
 
@@ -418,210 +384,228 @@ class OCI8
418
384
  # # or
419
385
  # OCI8::BindType.default_timezone = :utc
420
386
  #
421
- class Time
422
- if OCI8.oracle_client_version >= ORAVER_9_0
423
- def self.create(con, val, param, max_array_size) # :nodoc:
424
- if true # TODO: check Oracle server version
425
- TimeViaOCITimestampTZ.new(con, val, param, max_array_size)
426
- else
427
- TimeViaOCIDate.new(con, val, param, max_array_size)
428
- end
429
- end
430
- else
431
- def self.create(con, val, param, max_array_size) # :nodoc:
432
- TimeViaOCIDate.new(con, val, param, max_array_size)
433
- end
387
+ class Time < OCI8::BindType::OCITimestampTZ
388
+ include OCI8::BindType::Util
389
+
390
+ def set(val) # :nodoc:
391
+ super(datetime_to_array(val, :timestamp_tz))
392
+ end
393
+
394
+ def get() # :nodoc:
395
+ array_to_time(super(), nil)
434
396
  end
435
397
  end
436
398
 
437
- if OCI8.oracle_client_version >= ORAVER_9_0
438
- #--
439
- # OCI8::BindType::IntervalYM
440
- #++
441
- #
442
- # This is a helper class to select or bind Oracle data type
443
- # <tt>INTERVAL YEAR TO MONTH</tt>. The retrieved value is
444
- # the number of months between two timestamps.
445
- #
446
- # The value can be applied to \DateTime#>> to shift months.
447
- # It can be applied to \Time#months_since if activisupport has
448
- # been loaded.
449
- #
450
- # === How to select <tt>INTERVAL YEAR TO MONTH</tt>
451
- #
452
- # <tt>INTERVAL YEAR TO MONTH</tt> is selected as an Integer.
453
- #
454
- # conn.exec("select (current_timestamp - hiredate) year to month from emp") do |hired_months|
455
- # puts "hired_months = #{hired_months}"
456
- # end
457
- #
458
- # == How to bind <tt>INTERVAL YEAR TO MONTH</tt>
459
- #
460
- # You cannot bind a bind variable as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
461
- # It must be bound explicitly by OCI8::Cursor#bind_param.
462
- #
463
- # # output bind variable
464
- # cursor = conn.parse(<<-EOS)
465
- # BEGIN
466
- # :interval := (:ts1 - :ts2) YEAR TO MONTH;
467
- # END;
468
- # EOS
469
- # cursor.bind_param(:interval, nil, :interval_ym)
470
- # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
471
- # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
472
- # cursor.exec
473
- # cursor[:interval] # => 4 (months)
474
- # cursor.close
475
- #
476
- # # input bind variable
477
- # cursor = conn.parse(<<-EOS)
478
- # BEGIN
479
- # :ts1 := :ts2 + :interval;
480
- # END;
481
- # EOS
482
- # cursor.bind_param(:ts1, nil, DateTime)
483
- # cursor.bind_param(:ts2, Date.parse('1969-11-19'))
484
- # cursor.bind_param(:interval, 4, :interval_ym)
485
- # cursor.exec
486
- # cursor[:ts1].strftime('%Y-%m-%d') # => 1970-03-19
487
- # cursor.close
488
- #
489
- class IntervalYM < OCI8::BindType::OCIIntervalYM
490
- def set(val) # :nodoc:
491
- unless val.nil?
492
- val = [val / 12, val % 12]
493
- end
494
- super(val)
495
- end
496
- def get() # :nodoc:
497
- val = super()
498
- return nil if val.nil?
499
- year, month = val
500
- year * 12 + month
399
+ class LocalTime < OCI8::BindType::OCITimestamp
400
+ include OCI8::BindType::Util
401
+
402
+ def set(val) # :nodoc:
403
+ super(datetime_to_array(val, :timestamp))
404
+ end
405
+
406
+ def get() # :nodoc:
407
+ array_to_time(super(), :local)
408
+ end
409
+ end
410
+
411
+ class UTCTime < OCI8::BindType::OCITimestamp
412
+ include OCI8::BindType::Util
413
+
414
+ def set(val) # :nodoc:
415
+ super(datetime_to_array(val, :timestamp))
416
+ end
417
+
418
+ def get() # :nodoc:
419
+ array_to_time(super(), :utc)
420
+ end
421
+ end
422
+
423
+ #--
424
+ # OCI8::BindType::IntervalYM
425
+ #++
426
+ #
427
+ # This is a helper class to select or bind Oracle data type
428
+ # <tt>INTERVAL YEAR TO MONTH</tt>. The retrieved value is
429
+ # the number of months between two timestamps.
430
+ #
431
+ # The value can be applied to \DateTime#>> to shift months.
432
+ # It can be applied to \Time#months_since if activisupport has
433
+ # been loaded.
434
+ #
435
+ # === How to select <tt>INTERVAL YEAR TO MONTH</tt>
436
+ #
437
+ # <tt>INTERVAL YEAR TO MONTH</tt> is selected as an Integer.
438
+ #
439
+ # conn.exec("select (current_timestamp - hiredate) year to month from emp") do |hired_months|
440
+ # puts "hired_months = #{hired_months}"
441
+ # end
442
+ #
443
+ # == How to bind <tt>INTERVAL YEAR TO MONTH</tt>
444
+ #
445
+ # You cannot bind a bind variable as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
446
+ # It must be bound explicitly by OCI8::Cursor#bind_param.
447
+ #
448
+ # # output bind variable
449
+ # cursor = conn.parse(<<-EOS)
450
+ # BEGIN
451
+ # :interval := (:ts1 - :ts2) YEAR TO MONTH;
452
+ # END;
453
+ # EOS
454
+ # cursor.bind_param(:interval, nil, :interval_ym)
455
+ # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
456
+ # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
457
+ # cursor.exec
458
+ # cursor[:interval] # => 4 (months)
459
+ # cursor.close
460
+ #
461
+ # # input bind variable
462
+ # cursor = conn.parse(<<-EOS)
463
+ # BEGIN
464
+ # :ts1 := :ts2 + :interval;
465
+ # END;
466
+ # EOS
467
+ # cursor.bind_param(:ts1, nil, DateTime)
468
+ # cursor.bind_param(:ts2, Date.parse('1969-11-19'))
469
+ # cursor.bind_param(:interval, 4, :interval_ym)
470
+ # cursor.exec
471
+ # cursor[:ts1].strftime('%Y-%m-%d') # => 1970-03-19
472
+ # cursor.close
473
+ #
474
+ class IntervalYM < OCI8::BindType::OCIIntervalYM
475
+ def set(val) # :nodoc:
476
+ unless val.nil?
477
+ val = [val / 12, val % 12]
501
478
  end
502
- end # OCI8::BindType::IntervalYM
479
+ super(val)
480
+ end
481
+ def get() # :nodoc:
482
+ val = super()
483
+ return nil if val.nil?
484
+ year, month = val
485
+ year * 12 + month
486
+ end
487
+ end # OCI8::BindType::IntervalYM
503
488
 
504
- #--
505
- # OCI8::BindType::IntervalDS
506
- #++
507
- #
508
- # (new in 2.0)
509
- #
510
- # This is a helper class to select or bind Oracle data type
511
- # <tt>INTERVAL DAY TO SECOND</tt>. The retrieved value is
512
- # the number of seconds between two typestamps as a \Float.
513
- #
514
- # Note that it is the number days as a \Rational if
515
- # OCI8::BindType::IntervalDS.unit is :day or the ruby-oci8
516
- # version is prior to 2.0.3.
517
- #
518
- # == How to bind <tt>INTERVAL DAY TO SECOND</tt>
489
+ #--
490
+ # OCI8::BindType::IntervalDS
491
+ #++
492
+ #
493
+ # (new in 2.0)
494
+ #
495
+ # This is a helper class to select or bind Oracle data type
496
+ # <tt>INTERVAL DAY TO SECOND</tt>. The retrieved value is
497
+ # the number of seconds between two typestamps as a \Float.
498
+ #
499
+ # Note that it is the number days as a \Rational if
500
+ # OCI8::BindType::IntervalDS.unit is :day or the ruby-oci8
501
+ # version is prior to 2.0.3.
502
+ #
503
+ # == How to bind <tt>INTERVAL DAY TO SECOND</tt>
504
+ #
505
+ # You cannot bind a bind variable as <tt>INTERVAL DAY TO SECOND</tt>
506
+ # implicitly. It must be bound explicitly by OCI8::Cursor#bind_param.
507
+ #
508
+ # # output bind variable
509
+ # cursor = conn.parse(<<-EOS)
510
+ # BEGIN
511
+ # :interval := (:ts1 - :ts2) DAY TO SECOND(9);
512
+ # END;
513
+ # EOS
514
+ # cursor.bind_param(:interval, nil, :interval_ds)
515
+ # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
516
+ # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
517
+ # cursor.exec
518
+ # cursor[:interval] # => 10492615.0 seconds
519
+ # cursor.close
520
+ #
521
+ # # input bind variable
522
+ # cursor = conn.parse(<<-EOS)
523
+ # BEGIN
524
+ # :ts1 := :ts2 + :interval;
525
+ # END;
526
+ # EOS
527
+ # cursor.bind_param(:ts1, nil, DateTime)
528
+ # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
529
+ # cursor.bind_param(:interval, 10492615.0, :interval_ds)
530
+ # cursor.exec
531
+ # cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35
532
+ # cursor.close
533
+ #
534
+ class IntervalDS < OCI8::BindType::OCIIntervalDS
535
+ @@hour = 1 / 24.to_r
536
+ @@minute = @@hour / 60
537
+ @@sec = @@minute / 60
538
+ @@fsec = @@sec / 1000000000
539
+ @@unit = :second
540
+
541
+ # call-seq:
542
+ # OCI8::BindType::IntervalDS.unit -> :second or :day
519
543
  #
520
- # You cannot bind a bind variable as <tt>INTERVAL DAY TO SECOND</tt>
521
- # implicitly. It must be bound explicitly by OCI8::Cursor#bind_param.
544
+ # (new in 2.0.3)
522
545
  #
523
- # # output bind variable
524
- # cursor = conn.parse(<<-EOS)
525
- # BEGIN
526
- # :interval := (:ts1 - :ts2) DAY TO SECOND(9);
527
- # END;
528
- # EOS
529
- # cursor.bind_param(:interval, nil, :interval_ds)
530
- # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
531
- # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
532
- # cursor.exec
533
- # cursor[:interval] # => 10492615.0 seconds
534
- # cursor.close
546
+ # Retrieves the unit of interval.
547
+ def self.unit
548
+ @@unit
549
+ end
550
+
551
+ # call-seq:
552
+ # OCI8::BindType::IntervalDS.unit = :second or :day
535
553
  #
536
- # # input bind variable
537
- # cursor = conn.parse(<<-EOS)
538
- # BEGIN
539
- # :ts1 := :ts2 + :interval;
540
- # END;
541
- # EOS
542
- # cursor.bind_param(:ts1, nil, DateTime)
543
- # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
544
- # cursor.bind_param(:interval, 10492615.0, :interval_ds)
545
- # cursor.exec
546
- # cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35
547
- # cursor.close
554
+ # (new in 2.0.3)
548
555
  #
549
- class IntervalDS < OCI8::BindType::OCIIntervalDS
550
- @@hour = 1 / 24.to_r
551
- @@minute = @@hour / 60
552
- @@sec = @@minute / 60
553
- @@fsec = @@sec / 1000000000
554
- @@unit = :second
555
-
556
- # call-seq:
557
- # OCI8::BindType::IntervalDS.unit -> :second or :day
558
- #
559
- # (new in 2.0.3)
560
- #
561
- # Retrieves the unit of interval.
562
- def self.unit
563
- @@unit
556
+ # Changes the unit of interval. :second is the default.
557
+ def self.unit=(val)
558
+ case val
559
+ when :second, :day
560
+ @@unit = val
561
+ else
562
+ raise 'unit should be :second or :day'
564
563
  end
564
+ end
565
565
 
566
- # call-seq:
567
- # OCI8::BindType::IntervalDS.unit = :second or :day
568
- #
569
- # (new in 2.0.3)
570
- #
571
- # Changes the unit of interval. :second is the default.
572
- def self.unit=(val)
573
- case val
574
- when :second, :day
575
- @@unit = val
566
+ def set(val) # :nodoc:
567
+ unless val.nil?
568
+ if val < 0
569
+ is_minus = true
570
+ val = -val
576
571
  else
577
- raise 'unit should be :second or :day'
578
- end
579
- end
580
-
581
- def set(val) # :nodoc:
582
- unless val.nil?
583
- if val < 0
584
- is_minus = true
585
- val = -val
586
- else
587
- is_minus = false
588
- end
589
- if @@unit == :second
590
- day, val = val.divmod 86400
591
- hour, val = val.divmod 3600
592
- minute, val = val.divmod 60
593
- sec, val = val.divmod 1
594
- else
595
- day, val = val.divmod 1
596
- hour, val = (val * 24).divmod 1
597
- minute, val = (val * 60).divmod 1
598
- sec, val = (val * 60).divmod 1
599
- end
600
- fsec, val = (val * 1000000000).divmod 1
601
- if is_minus
602
- day = - day
603
- hour = - hour
604
- minute = - minute
605
- sec = - sec
606
- fsec = - fsec
607
- end
608
- val = [day, hour, minute, sec, fsec]
572
+ is_minus = false
609
573
  end
610
- super(val)
611
- end
612
-
613
- def get() # :nodoc:
614
- val = super()
615
- return nil if val.nil?
616
- day, hour, minute, sec, fsec = val
617
574
  if @@unit == :second
618
- fsec = fsec / 1000000000.0
619
- day * 86400 + hour * 3600 + minute * 60 + sec + fsec
575
+ day, val = val.divmod 86400
576
+ hour, val = val.divmod 3600
577
+ minute, val = val.divmod 60
578
+ sec, val = val.divmod 1
620
579
  else
621
- day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
580
+ day, val = val.divmod 1
581
+ hour, val = (val * 24).divmod 1
582
+ minute, val = (val * 60).divmod 1
583
+ sec, val = (val * 60).divmod 1
584
+ end
585
+ fsec, val = (val * 1000000000).divmod 1
586
+ if is_minus
587
+ day = - day
588
+ hour = - hour
589
+ minute = - minute
590
+ sec = - sec
591
+ fsec = - fsec
622
592
  end
593
+ val = [day, hour, minute, sec, fsec]
623
594
  end
624
- end # OCI8::BindType::IntervalDS
625
- end
595
+ super(val)
596
+ end
597
+
598
+ def get() # :nodoc:
599
+ val = super()
600
+ return nil if val.nil?
601
+ day, hour, minute, sec, fsec = val
602
+ if @@unit == :second
603
+ fsec = fsec / 1000000000.0
604
+ day * 86400 + hour * 3600 + minute * 60 + sec + fsec
605
+ else
606
+ day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
607
+ end
608
+ end
609
+ end # OCI8::BindType::IntervalDS
626
610
  end # OCI8::BindType
627
611
  end # OCI8