ruby-oci8 2.0.2-x86-mswin32-60 → 2.0.3-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog CHANGED
@@ -1,3 +1,124 @@
1
+ 2009-10-21 KUBO Takehiro <kubo@jiubao.org>
2
+ * NEWS: add changes between 2.0.2 and 2.0.3.
3
+ * VERSION, Makefile: change the version to 2.0.3.
4
+ * ext/oci8/oci8.c: fix typo.
5
+ * ext/oci8/apiwrap.yml: add OCIIntervalFromText() prototype.
6
+
7
+ 2009-10-18 KUBO Takehiro <kubo@jiubao.org>
8
+ * ext/oci8/ocidatetime.c: Add workarounds for Oracle 9.2.0.1.
9
+ * lib/oci8/datetime.rb: Change the unit of OCI8::BindType::IntervalDS
10
+ from day to second. Add OCI8::BindType::IntervalDS.unit and
11
+ OCI8::BindType::IntervalDS.unit=.
12
+ * test/test_datetime.rb: Fix tests for the above changes.
13
+
14
+ 2009-10-17 KUBO Takehiro <kubo@jiubao.org>
15
+ * ext/oci8/oci8.c: Add a workaround for Oracle 9.2.0.1 when clearing
16
+ a client identifier.
17
+ * ext/oci8/oci8lib.c: Fix a segv when canceling a non-blocking
18
+ execution.
19
+ * test_appinfo.rb: Fix temporarily to prevent a segmentation fault
20
+ under Oracle 9.2.0.1.
21
+ * test/test_oci8.rb: Fix temporarily to prevent a segmentation fault
22
+ under Oracle 9.2.0.1. Fix for BigDecimal bundled in ruby 1.8.5.
23
+ * test/test_oranumber.rb: Fix for Oracle 9.2. Comparing float values
24
+ by <=> is too sensitive to use it in tests.
25
+
26
+ 2009-10-06 KUBO Takehiro <kubo@jiubao.org>
27
+ * ext/oci8/ocinumber.c: Add a global function OraNumber(obj) as a
28
+ shortcut of OraNumber.new(obj) as Rational and BigDecimal do.
29
+ Changes the return type of the four rules of arithmetic;
30
+ addition, subtraction, multiplication and division. It was
31
+ OraNumber, but now it depends on the operand.
32
+ * lib/oci8/bindtype.rb: Add OCI8::BindType::BigDecimal and
33
+ OCI8::BindType::Rational. Change the default data type for
34
+ number column which fit neither Integer nor Float from
35
+ OraNumber to BigDecimal.
36
+ * lib/oci8/oci8.rb: Fix for OCI8::BindType::Mapping to accept
37
+ a class name instead of the class object to support
38
+ OCI8::BindType::BigDecimal and OCI8::BindType::Rational without
39
+ requiring 'bigdecimal' and 'rational'.
40
+ * spec/oranumber_spec.rb: Add a spec file for OraNumber arithmetic.
41
+ * test/test_oci8.rb: Add tests for OCI8::BindType::BigDecimal and
42
+ OCI8::BindType::Rational.
43
+
44
+ 2009-10-04 KUBO Takehiro <kubo@jiubao.org>
45
+ * ext/oci8/oci8.c: Add constants missing in Oracle client prior to 10g.
46
+ * ext/oci8/oraconf.rb:
47
+ 1. Fix for ruby 1.8.5 with Oracle 8.x which needs some object
48
+ files to link with.
49
+ (reported by Jayson Cena)
50
+ 2. Revise the error message under the sudo environemnt.
51
+ 3. Print not only error message but also the error backtrace when
52
+ oraconf.rb fails.
53
+ * lib/oci8/object.rb: Fix to accept nil attribute in object type's
54
+ constructors. This works only for simple data types such as number,
55
+ string. But it doesn't for complex types such as object types.
56
+ (requested by Remi Gagnon)
57
+ * spec/object_type_spec.rb: Add a test for object type's constructors.
58
+
59
+ 2009-09-22 KUBO Takehiro <kubo@jiubao.org>
60
+ * lib/oci8/.document, lib/oci8/datetime.rb: 1. Add
61
+ OCI8::BindType.default_timezone and OCI8::BindType.default_timezone=.
62
+ 2. Change the logic to convert to Time and DateTime to adapt DST.
63
+ 3. Use new features of Time class in ruby 1.9.2 if they are available.
64
+ 4. Add rdoc comments.
65
+ * spec/fetch_datetime8_spec.rb, spec/fetch_datetime_spec.rb,
66
+ spec/fetch_time8_spec.rb, spec/fetch_time_spec.rb,
67
+ spec/spec_helper.rb: Add tests for OCI8::BindType::DateTime and
68
+ OCI8::BindType::Time.
69
+
70
+ 2009-09-13 KUBO Takehiro <kubo@jiubao.org>
71
+ * ext/oci8/lob.c, ext/oci8/oci8.h, test/test_clob.rb: Change
72
+ OCI8::LOB#write to accept an object which is not a String and
73
+ doesn't respond to 'to_str' as IO#write does.
74
+ (requested by Christopher Jones)
75
+
76
+ 2009-09-12 KUBO Takehiro <kubo@jiubao.org>
77
+ * ext/oci8/extconf.rb, lib/oci8.rb.in: Fixed for ruby 1.9.2 preview1.
78
+ (pointed by Raimonds Simanovskis)
79
+
80
+ 2009-09-12 KUBO Takehiro <kubo@jiubao.org>
81
+ * ext/oci8/oraconf.rb: Fixed to compile for AIX instant clients.
82
+ (reported by Kazuya Teramoto)
83
+
84
+ 2009-06-09 KUBO Takehiro <kubo@jiubao.org>
85
+ * ext/oci8/oci8lib.c: Change the initial polling interval of
86
+ non-blocking mode for ruby 1.8 from 100 msec to 10 msec, which
87
+ is same with ruby-oci8 1.0.
88
+ * ext/oci8/oci8.c: Change the default setting of non-blocking mode
89
+ for ruby 1.9 to true. Revise rdoc comments.
90
+
91
+ 2009-06-07 KUBO Takehiro <kubo@jiubao.org>
92
+ * ext/oci8/oci8.c: revise rdoc comments.
93
+
94
+ 2009-06-05 KUBO Takehiro <kubo@jiubao.org>
95
+ * Makefile: check rdoc version when making rdoc documentation.
96
+ The rdoc version must be 2.4.
97
+ * ext/oci8/.document, ext/oci8/oci8.c, lib/.document,
98
+ lib/oci8/.document, lib/oci8/oci8.rb: fix rdoc comments a bit.
99
+
100
+ 2009-05-24 KUBO Takehiro <kubo@jiubao.org>
101
+ * ext/oci8/object.c, lib/oci8/datetime.rb, lib/oci8/object.rb:
102
+ add DATE datatype support in object types.
103
+
104
+ 2009-05-19 KUBO Takehiro <kubo@jiubao.org>
105
+ * ext/oci8/bind.c: delete OCI8::BindType::Fixnum.
106
+ * lib/oci8/compat.rb: add OCI8::BindType::Fixnum as an alias
107
+ of OCI8::BindType::Integer.
108
+ * ext/oci8/extconf.rb: change extconf.rb's argument value of
109
+ '--with-oracle-version' to accept dotted version such as
110
+ '9.2.0.'
111
+ * ext/oci8/oraconf.rb: When extconf.rb fails and it is run
112
+ by sudo command, change the error message to notice that
113
+ 'sudo' may unset environment variables.
114
+
115
+ 2009-05-18 KUBO Takehiro <kubo@jiubao.org>
116
+ * ext/oci8/oci8.c: revise rdoc comments for OCI8#ping and
117
+ OCI8#client_identifier=. Add OCI8#module=, OCI8#action= and
118
+ OCI8#client_info.
119
+ * test/test_appinfo.rb: add test cases for OCI8#module=,
120
+ OCI8#action= and OCI8#client_info.
121
+
1
122
  2009-05-17 KUBO Takehiro <kubo@jiubao.org>
2
123
  * NEWS: add changes between 2.0.1 and 2.0.2.
3
124
  * VERSION: change version to 2.0.2.
data/Makefile CHANGED
@@ -1,5 +1,6 @@
1
1
  VERSION = `cat VERSION`
2
2
  RUBY = ruby -w
3
+ RDOC = rdoc
3
4
 
4
5
  all: build
5
6
 
@@ -30,10 +31,16 @@ format_c_source:
30
31
  astyle --options=none --style=linux --indent=spaces=4 --brackets=linux --suffix=none ext/oci8/*.[ch]
31
32
 
32
33
  # internal use only
33
- .PHONY: rdoc
34
+ .PHONY: rdoc check-rdoc-version run-rdoc
34
35
 
35
- rdoc:
36
- $(RUBY) custom-rdoc.rb -o rdoc -U README ext/oci8 lib
36
+ rdoc: check-rdoc-version run-rdoc
37
+
38
+ check-rdoc-version:
39
+ @echo check rdoc version
40
+ @expr match "`$(RDOC) --version`" '^rdoc 2\.4' > /dev/null || (echo 'rdoc version is not 2.4.'; exit 1)
41
+
42
+ run-rdoc:
43
+ TZ= $(RDOC) -o rdoc -c us-ascii --threads=1 -W http://ruby-oci8.rubyforge.org/svn/trunk/ruby-oci8/ ext/oci8 lib
37
44
 
38
45
  dist:
39
46
  -rm -rf ruby-oci8-$(VERSION)
@@ -52,7 +59,7 @@ dist-check: dist
52
59
  #
53
60
  RUBY_18 = c:\ruby
54
61
  RUBY_191 = c:\ruby-1.9.1
55
- GEMPKG = ruby-oci8-2.0.2-x86-mswin32-60.gem
62
+ GEMPKG = ruby-oci8-2.0.3-x86-mswin32-60.gem
56
63
 
57
64
  ext\oci8\oci8lib_18.so:
58
65
  $(RUBY_18)\bin\ruby -r fileutils -e "FileUtils.rm_rf('ruby18')"
data/NEWS CHANGED
@@ -1,3 +1,129 @@
1
+ 2.0.3:
2
+
3
+ * Imcompatible Changes
4
+
5
+ - Number column in a SQL statement
6
+
7
+ Changes the default data type for number column which fit neither
8
+ Integer nor Float from OraNumber to BigDecimal.
9
+
10
+ conn.exec("select 1.0 from dual") do |row|
11
+ p row[0] # => BigDecimal("1") if the ruby-oci8 version is 2.0.3.
12
+ # => OraNumber(1) if the version is 2.0.2.
13
+ end
14
+
15
+ - Priority of OraNumber within numerical types
16
+
17
+ The return types of basic arithmetic operations with other numerical
18
+ types are changed.
19
+
20
+ 2.0.3:
21
+ OraNumber + Integer => OraNumber (OraNumber wins.)
22
+ OraNumber + Float => Float (OraNumber loses.)
23
+ OraNumber + Rational => Rational (OraNumber loses.)
24
+ OraNumber + BigDecimal => BigDecimal (OraNumber loses.)
25
+
26
+ 2.0.2:
27
+ OraNumber + Integer => OraNumber (OraNumber wins always.)
28
+ OraNumber + Float => OraNumber
29
+ OraNumber + Rational => OraNumber
30
+ OraNumber + BigDecimal => OraNumber
31
+
32
+ - Interval day to second
33
+
34
+ The retrived value of Oracle data type "interval day to second"
35
+ was changed from the number of days as a Rational to the number
36
+ of seconds as a Float by default.
37
+ Use OCI8::BindType::IntervalDS.unit = :day to make it compatible
38
+ with the previous versions.
39
+
40
+ conn.exec("select to_dsinterval('0 00:00:01') from dual") do |row|
41
+ p row[0] # => 1.0 if the version is 2.0.3 and
42
+ # OCI8::BindType::IntervalDS.unit is :second.
43
+ # => (1/86400) if the version is 2.0.3 and
44
+ # OCI8::BindType::IntervalDS.unit is :day or
45
+ # the version is 2.0.2.
46
+ end
47
+
48
+ - Date, timestamp, timestamp with time zone data types and ruby 1.9.2
49
+
50
+ These data types are retrived always as Time values when the
51
+ ruby version is 1.9.2 because the Time class is enhanced to
52
+ represent any time zone and is free from year 2038 problem.
53
+
54
+ Prior to ruby 1.9.2, if the time cannot be represented by
55
+ Unix time or the time zone is neither utc nor local, they are
56
+ retrived as DateTime values.
57
+
58
+ - Non-blocking mode and ruby 1.9
59
+
60
+ non-blocking mode is enabled by default when the ruby is 1.9.
61
+
62
+ * New Features
63
+
64
+ - BigDecimal and Rational are availabe as bind values.
65
+
66
+ - New methods OCI8#module=, OCI8#action= and OCI8#client_info= are added.
67
+
68
+ These methods change the module name, the action name and the client_info
69
+ in the current session respectively.
70
+
71
+ After Oracle 10g client, these don't perform network round trips.
72
+ The change is reflected to the server by the next round trip such as
73
+ OCI8#exec, OCI8#ping, etc.
74
+
75
+ Prior to Oracle 10g client, these call PL/SQL functions such as
76
+ DBMS_APPLICATION_INFO.SET_MODULE, DBMS_APPLICATION_INFO.SET_ACTION,
77
+ and DBMS_APPLICATION_INFO.SET_CLIENT_INFO internally.
78
+ The change is reflected immediately by a network round trip.
79
+
80
+ - OCI8::BindType.default_timezone
81
+
82
+ The default time zone of Time or DateTime values.
83
+ This parameter is used only when
84
+ (1) date values are fetched and the Oracle client version is 8.x
85
+ or
86
+ (2) object types have date data type attributes.
87
+
88
+ Note that if the Oracle client version is 9i or upper, the time
89
+ zone is determined by the session time zone. The default value
90
+ is local time zone. You can change it to GMT by executing the
91
+ following SQL statement for each connection.
92
+
93
+ alter session set time_zone = '00:00'
94
+
95
+ * Other specification changes
96
+
97
+ - Add a global function OraNumber(obj) as a shortcut of OraNumber.new(obj)
98
+ as Rational and BigDecimal do.
99
+
100
+ - Fix to accept nil attribute in object type's
101
+ constructors. This works only for simple data types such as number,
102
+ string. But it doesn't for complex types such as object types.
103
+ (requested by Remi Gagnon)
104
+
105
+ - add DATE datatype support in object types.
106
+
107
+ - Change OCI8::LOB#write to accept an object which is not a String and
108
+ doesn't respond to 'to_str' as IO#write does.
109
+ (requested by Christopher Jones)
110
+
111
+ - Change the initial polling interval of
112
+ non-blocking mode for ruby 1.8 from 100 msec to 10 msec, which
113
+ is same with ruby-oci8 1.0.
114
+
115
+ * Fixed installation issues.
116
+
117
+ - Fix oraconf.rb for ruby 1.8.5 with Oracle 8.x which needs some object
118
+ files to link with.
119
+ (reported by Jayson Cena)
120
+
121
+ - Fix oraconf.rb for ruby 1.9.2 preview1.
122
+ (pointed by Raimonds Simanovskis)
123
+
124
+ - Fix oraconf.rb to compile for AIX instant clients.
125
+ (reported by Kazuya Teramoto)
126
+
1
127
  2.0.2:
2
128
 
3
129
  * add new methods
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.2
1
+ 2.0.3
data/lib/.document CHANGED
@@ -1,2 +1 @@
1
1
  oci8
2
- oci8.rb
data/lib/oci8.rb CHANGED
@@ -19,7 +19,7 @@ if RUBY_PLATFORM =~ /cygwin/
19
19
  end
20
20
 
21
21
  case RUBY_VERSION
22
- when /^1\.9\.1/
22
+ when /^1\.9/
23
23
  require 'oci8lib_191'
24
24
  when /^1\.8/
25
25
  require 'oci8lib_18'
@@ -77,6 +77,6 @@ require 'oci8/compat.rb'
77
77
  require 'oci8/object.rb'
78
78
 
79
79
  class OCI8
80
- VERSION = '2.0.2'
80
+ VERSION = '2.0.3'
81
81
  CLIENT_VERSION = '1020'
82
82
  end
data/lib/oci8.rb.in CHANGED
@@ -19,7 +19,7 @@ if RUBY_PLATFORM =~ /cygwin/
19
19
  end
20
20
 
21
21
  case RUBY_VERSION
22
- when /^1\.9\.1/
22
+ when /^1\.9/
23
23
  require 'oci8lib_191'
24
24
  when /^1\.8/
25
25
  require 'oci8lib_18'
data/lib/oci8/.document CHANGED
@@ -1,5 +1,5 @@
1
- oci8.rb
1
+ datetime.rb
2
2
  object.rb
3
3
  metadata.rb
4
4
  oracle_version.rb
5
-
5
+ oci8.rb
data/lib/oci8/bindtype.rb CHANGED
@@ -24,6 +24,28 @@ class OCI8
24
24
  end
25
25
  end
26
26
 
27
+ class BigDecimal < OCI8::BindType::OraNumber
28
+ @@bigdecimal_is_required = false
29
+ def get()
30
+ unless @@bigdecimal_is_required
31
+ require 'bigdecimal'
32
+ @@bigdecimal_is_required = true
33
+ end
34
+ (val = super()) && val.to_d
35
+ end
36
+ end
37
+
38
+ class Rational < OCI8::BindType::OraNumber
39
+ @@rational_is_required = false
40
+ def get()
41
+ unless @@rational_is_required
42
+ require 'rational'
43
+ @@rational_is_required = true
44
+ end
45
+ (val = super()) && val.to_r
46
+ end
47
+ end
48
+
27
49
  # get/set Number (for OCI8::SQLT_NUM)
28
50
  class Number
29
51
  def self.create(con, val, param, max_array_size)
@@ -54,8 +76,8 @@ class OCI8
54
76
  if precision < 15 # the precision of double.
55
77
  klass = OCI8::BindType::Float
56
78
  else
57
- # use BigDecimal instead?
58
- klass = OCI8::BindType::OraNumber
79
+ # use BigDecimal instead
80
+ klass = OCI8::BindType::BigDecimal
59
81
  end
60
82
  end
61
83
  klass.new(con, val, nil, max_array_size)
@@ -156,6 +178,8 @@ end
156
178
  # bind or explicitly define
157
179
  OCI8::BindType::Mapping[String] = OCI8::BindType::String
158
180
  OCI8::BindType::Mapping[OraNumber] = OCI8::BindType::OraNumber
181
+ OCI8::BindType::Mapping['BigDecimal'] = OCI8::BindType::BigDecimal
182
+ OCI8::BindType::Mapping['Rational'] = OCI8::BindType::Rational
159
183
  OCI8::BindType::Mapping[Fixnum] = OCI8::BindType::Integer
160
184
  OCI8::BindType::Mapping[Float] = OCI8::BindType::Float
161
185
  OCI8::BindType::Mapping[Integer] = OCI8::BindType::Integer
@@ -263,9 +287,9 @@ OCI8::BindType::Mapping[:number] = OCI8::BindType::Number
263
287
  # datatypes that have no explicit setting of their precision
264
288
  # and scale.
265
289
  #
266
- # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
267
- # for ruby-oci8 2.0.
268
- OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
290
+ # The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2,
291
+ # BigDecimal for 2.0.3 ~.
292
+ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::BigDecimal
269
293
 
270
294
  # mapping for number without precision and scale.
271
295
  #
@@ -276,9 +300,9 @@ OCI8::BindType::Mapping[:number_unknown_prec] = OCI8::BindType::OraNumber
276
300
  # note: This is available only on Oracle 9.2.0.3 or above.
277
301
  # see: Oracle 9.2.0.x Patch Set Notes.
278
302
  #
279
- # The default mapping is Float for ruby-oci8 1.0. It is OraNumber
280
- # for ruby-oci8 2.0.
281
- OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::OraNumber
303
+ # The default mapping is Float for ruby-oci8 1.0, OraNumber for 2.0.0 ~ 2.0.2,
304
+ # BigDecimal for 2.0.3 ~.
305
+ OCI8::BindType::Mapping[:number_no_prec_setting] = OCI8::BindType::BigDecimal
282
306
 
283
307
  if defined? OCI8::BindType::BinaryDouble
284
308
  OCI8::BindType::Mapping[:binary_float] = OCI8::BindType::BinaryDouble
data/lib/oci8/compat.rb CHANGED
@@ -105,4 +105,9 @@ class OCI8
105
105
  # add alias compatible with 'Oracle7 Module for Ruby'.
106
106
  alias getColNames get_col_names
107
107
  end
108
+
109
+ module BindType
110
+ # alias to Integer for compatibility with ruby-oci8 1.0.
111
+ Fixnum = Integer
112
+ end
108
113
  end
data/lib/oci8/datetime.rb CHANGED
@@ -4,23 +4,44 @@ class OCI8
4
4
 
5
5
  module BindType
6
6
 
7
+ # call-seq:
8
+ # OCI8::BindType.default_timezone -> :local or :utc
9
+ #
10
+ # Returns the default time zone when using Oracle 8.x client.
11
+ # The value is unused when using Oracle 9i or upper client.
12
+ #
13
+ # See also: OCI8::BindType::Time
14
+ def self.default_timezone
15
+ OCI8::BindType::Util.default_timezone
16
+ end
17
+
18
+ # call-seq:
19
+ # OCI8::BindType.default_timezone = :local or :utc
20
+ #
21
+ # Sets the default time zone when using Oracle 8.x client.
22
+ # The value is unused when using Oracle 9i or upper client.
23
+ #
24
+ # See also: OCI8::BindType::Time
25
+ def self.default_timezone=(tz)
26
+ OCI8::BindType::Util.default_timezone = tz
27
+ end
28
+
7
29
  module Util # :nodoc:
8
30
 
9
31
  @@datetime_fsec_base = (1 / ::DateTime.parse('0001-01-01 00:00:00.000000001').sec_fraction).to_i
10
- @@time_offset = ::Time.now.utc_offset
11
- @@datetime_offset = ::DateTime.now.offset
12
32
 
13
33
  @@default_timezone = :local
34
+ begin
35
+ Time.new(2001, 1, 1, 0, 0, 0, '+00:00')
36
+ @@time_new_accepts_timezone = true # after ruby 1.9.2
37
+ rescue ArgumentError
38
+ @@time_new_accepts_timezone = false # prior to ruby 1.9.2
39
+ end
40
+
14
41
  def self.default_timezone
15
42
  @@default_timezone
16
43
  end
17
44
 
18
- # Determines default timezone of Time and DateTime retrived from Oracle.
19
- # This accepts :local or :utc. The default is :local.
20
- #
21
- # This parameter is used when both or either of Oracle server and client
22
- # version is Oracle 8i or lower. If both versions are Oracle 9i or upper,
23
- # the default timezone is determined by the session timezone.
24
45
  def self.default_timezone=(tz)
25
46
  if tz != :local and tz != :utc
26
47
  raise ArgumentError, "expected :local or :utc but #{tz}"
@@ -31,6 +52,8 @@ class OCI8
31
52
  private
32
53
 
33
54
  def datetime_to_array(val, full)
55
+ return nil if val.nil?
56
+
34
57
  # year
35
58
  year = val.year
36
59
  # month
@@ -100,9 +123,16 @@ class OCI8
100
123
  end
101
124
 
102
125
  def ocidate_to_datetime(ary)
126
+ return nil if ary.nil?
127
+
103
128
  year, month, day, hour, minute, sec = ary
104
129
  if @@default_timezone == :local
105
- offset = @@datetime_offset
130
+ if ::DateTime.respond_to? :local_offset
131
+ offset = ::DateTime.local_offset # Use a method defined by active support.
132
+ else
133
+ # Do as active support does.
134
+ offset = ::Time.local(2007).utc_offset.to_r / 86400
135
+ end
106
136
  else
107
137
  offset = 0
108
138
  end
@@ -110,8 +140,10 @@ class OCI8
110
140
  end
111
141
 
112
142
  def ocidate_to_time(ary)
143
+ return nil if ary.nil?
144
+
113
145
  year, month, day, hour, minute, sec = ary
114
- if year >= 139
146
+ if @@time_new_accepts_timezone || year >= 139 || year < 0
115
147
  begin
116
148
  return ::Time.send(@@default_timezone, year, month, day, hour, minute, sec)
117
149
  rescue StandardError
@@ -123,6 +155,8 @@ class OCI8
123
155
  if OCI8.oracle_client_version >= ORAVER_9_0
124
156
 
125
157
  def ocitimestamp_to_datetime(ary)
158
+ return nil if ary.nil?
159
+
126
160
  year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
127
161
  if sec >= 59 and fsec != 0
128
162
  # convert to a DateTime via a String as a last resort.
@@ -143,168 +177,159 @@ class OCI8
143
177
  end
144
178
  end
145
179
 
146
- def ocitimestamp_to_time(ary)
147
- year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
180
+ if @@time_new_accepts_timezone
181
+
182
+ # after ruby 1.9.2
183
+ def ocitimestamp_to_time(ary)
184
+ return nil if ary.nil?
148
185
 
149
- if tz_hour == 0 and tz_min == 0
150
- timezone = :utc
151
- elsif @@time_offset == tz_hour * 3600 + tz_min * 60
152
- timezone = :local
186
+ year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
187
+
188
+ sec += fsec / Rational(1000000000)
189
+ utc_offset = tz_hour * 3600 + tz_min * 60
190
+ return ::Time.new(year, month, day, hour, minute, sec, utc_offset)
153
191
  end
154
- if timezone and year >= 139
155
- begin
156
- # Ruby 1.9 Time class's resolution is nanosecond.
157
- # But the last argument type is millisecond.
158
- # 'fsec' is converted to a Float to pass sub-millisecond part.
159
- return ::Time.send(timezone, year, month, day, hour, minute, sec, fsec / 1000.0)
160
- rescue StandardError
192
+
193
+ else
194
+
195
+ # prior to ruby 1.9.2
196
+ def ocitimestamp_to_time(ary)
197
+ return nil if ary.nil?
198
+
199
+ year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
200
+
201
+ if year >= 139 || year < 0
202
+ begin
203
+ if tz_hour == 0 and tz_min == 0
204
+ return ::Time.utc(year, month, day, hour, minute, sec, fsec / Rational(1000))
205
+ else
206
+ tm = ::Time.local(year, month, day, hour, minute, sec, fsec / Rational(1000))
207
+ return tm if tm.utc_offset == tz_hour * 3600 + tz_min * 60
208
+ end
209
+ rescue StandardError
210
+ end
161
211
  end
212
+ ocitimestamp_to_datetime(ary)
162
213
  end
163
- ocitimestamp_to_datetime(ary)
214
+
164
215
  end
165
216
  end
166
217
  end
167
218
 
168
- class DateTimeViaOCIDate < OCI8::BindType::OCIDate
219
+ class DateTimeViaOCIDate < OCI8::BindType::OCIDate # :nodoc:
169
220
  include OCI8::BindType::Util
170
221
 
171
222
  def set(val) # :nodoc:
172
- val &&= datetime_to_array(val, false)
173
- super(val)
223
+ super(datetime_to_array(val, false))
174
224
  end
175
225
 
176
226
  def get() # :nodoc:
177
- val = super()
178
- val ? ocidate_to_datetime(val) : nil
227
+ ocidate_to_datetime(super())
179
228
  end
180
229
  end
181
230
 
182
- class TimeViaOCIDate < OCI8::BindType::OCIDate
231
+ class TimeViaOCIDate < OCI8::BindType::OCIDate # :nodoc:
183
232
  include OCI8::BindType::Util
184
233
 
185
234
  def set(val) # :nodoc:
186
- val &&= datetime_to_array(val, false)
187
- super(val)
235
+ super(datetime_to_array(val, false))
188
236
  end
189
237
 
190
238
  def get() # :nodoc:
191
- val = super()
192
- val ? ocidate_to_time(val) : nil
239
+ ocidate_to_time(super())
193
240
  end
194
241
  end
195
242
 
196
243
  if OCI8.oracle_client_version >= ORAVER_9_0
197
- class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp
244
+ class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
198
245
  include OCI8::BindType::Util
199
246
 
200
247
  def set(val) # :nodoc:
201
- val &&= datetime_to_array(val, true)
202
- super(val)
248
+ super(datetime_to_array(val, true))
203
249
  end
204
250
 
205
251
  def get() # :nodoc:
206
- val = super()
207
- val ? ocitimestamp_to_datetime(val) : nil
252
+ ocitimestamp_to_datetime(super())
208
253
  end
209
254
  end
210
255
 
211
- class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp
256
+ class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp # :nodoc:
212
257
  include OCI8::BindType::Util
213
258
 
214
259
  def set(val) # :nodoc:
215
- val &&= datetime_to_array(val, true)
216
- super(val)
260
+ super(datetime_to_array(val, true))
217
261
  end
218
262
 
219
263
  def get() # :nodoc:
220
- val = super()
221
- val ? ocitimestamp_to_time(val) : nil
264
+ ocitimestamp_to_time(super())
222
265
  end
223
266
  end
224
267
  end
225
268
 
226
-
227
269
  #--
228
270
  # OCI8::BindType::DateTime
229
271
  #++
230
- # This is a helper class to bind ruby's
231
- # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]
232
- # object as Oracle's <tt>TIMESTAMP WITH TIME ZONE</tt> datatype.
272
+ # This is a helper class to select or bind Oracle data types such as
273
+ # <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
274
+ # and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt>. The retrieved value
275
+ # is a \DateTime.
276
+ #
277
+ # === How to select \DataTime values.
278
+ #
279
+ # <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
280
+ # and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> are selected as a \Time
281
+ # by default. You change the behaviour by explicitly calling
282
+ # OCI8::Cursor#define as follows:
283
+ #
284
+ # cursor = conn.parse("SELECT hiredate FROM emp")
285
+ # cursor.define(1, nil, DateTime)
286
+ # cursor.exec()
287
+ #
288
+ # Otherwise, you can change the default mapping for all queries.
233
289
  #
234
- # == Select
290
+ # # Changes the mapping for DATE
291
+ # OCI8::BindType::Mapping[OCI8::SQLT_DAT] = OCI8::BindType::DateTime
292
+ #
293
+ # # Changes the mapping for TIMESTAMP
294
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::DateTime
295
+ #
296
+ # # Changes the mapping for TIMESTAMP WITH TIME ZONE
297
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::DateTime
298
+ #
299
+ # # Changes the mapping for TIMESTAMP WITH LOCAL TIME ZONE
300
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::DateTime
235
301
  #
236
- # The fetched value for a <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH
237
- # TIME ZONE</tt> or <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> column
238
- # is a DateTime[http://www.ruby-doc.org/core/classes/DateTime.html].
239
- # The time zone part is a session time zone if the Oracle datatype doesn't
240
- # have time zone information. The session time zone is the client machine's
241
- # time zone by default.
302
+ # === Note for default time zone
242
303
  #
243
- # You can change the session time zone by executing the following SQL.
304
+ # The retrieved value's time zone is determined by the session time zone
305
+ # if its data type is <tt>DATE</tt>, <tt>TIMESTAMP</tt> or <tt>TIMESTAMP
306
+ # WITH LOCAL TIME ZONE</tt>.
307
+ #
308
+ # The session time zone is same with local machine's by default.
309
+ # It is changed by the following SQL.
244
310
  #
245
311
  # ALTER SESSION SET TIME_ZONE='-05:00'
246
312
  #
247
- # == Bind
248
- #
249
- # To bind a DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]
250
- # value implicitly:
251
- #
252
- # conn.exec("INSERT INTO lunar_landings(ship_name, landing_time) VALUES(:1, :2)",
253
- # 'Apollo 11',
254
- # DateTime.parse('1969-7-20 20:17:40 00:00'))
255
- #
256
- # The bind variable <code>:2</code> is bound as <tt>TIMESTAMP WITH TIME ZONE</tt> on Oracle.
257
- #
258
- # To bind explicitly:
259
- #
260
- # cursor = conn.exec("INSERT INTO lunar_landings(ship_name, landing_time) VALUES(:1, :2)")
261
- # cursor.bind_param(':1', nil, String, 60)
262
- # cursor.bind_param(':2', nil, DateTime)
263
- # [['Apollo 11', DateTime.parse('1969-07-20 20:17:40 00:00'))],
264
- # ['Apollo 12', DateTime.parse('1969-11-19 06:54:35 00:00'))],
265
- # ['Apollo 14', DateTime.parse('1971-02-05 09:18:11 00:00'))],
266
- # ['Apollo 15', DateTime.parse('1971-07-30 22:16:29 00:00'))],
267
- # ['Apollo 16', DateTime.parse('1972-04-21 02:23:35 00:00'))],
268
- # ['Apollo 17', DateTime.parse('1972-12-11 19:54:57 00:00'))]
269
- # ].each do |ship_name, landing_time|
270
- # cursor[':1'] = ship_name
271
- # cursor[':2'] = landing_time
272
- # cursor.exec
273
- # end
274
- # cursor.close
275
- #
276
- # On setting a object to the bind variable, you can use any object
277
- # which has at least three instance methods _year_, _mon_ (or _month_)
278
- # and _mday_ (or _day_). If the object responses to _hour_, _min_,
279
- # _sec_ or _sec_fraction_, the responsed values are used for hour,
280
- # minute, second or fraction of a second respectively.
281
- # If not, zeros are set. If the object responses to _offset_ or
282
- # _utc_offset_, it is used for time zone. If not, the session time
283
- # zone is used.
284
- #
285
- # The acceptable value are listed below.
286
- # _year_:: -4712 to 9999 [excluding year 0]
287
- # _mon_ (or _month_):: 0 to 12
288
- # _mday_ (or _day_):: 0 to 31 [depends on the month]
289
- # _hour_:: 0 to 23
290
- # _min_:: 0 to 59
291
- # _sec_:: 0 to 59
292
- # _sec_fraction_:: 0 to (999_999_999.to_r / (24*60*60* 1_000_000_000)) [999,999,999 nanoseconds]
293
- # _offset_:: (-12.to_r / 24) to (14.to_r / 24) [-12:00 to +14:00]
294
- # _utc_offset_:: -12*3600 <= utc_offset <= 24*3600 [-12:00 to +14:00]
295
- #
296
- # The output value of the bind varible is always a
297
- # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html].
298
- #
299
- # cursor = conn.exec("BEGIN :ts := current_timestamp; END")
300
- # cursor.bind_param(:ts, nil, DateTime)
301
- # cursor.exec
302
- # cursor[:ts] # => a DateTime.
303
- # cursor.close
313
+ # === Note for Oracle 8.x client
314
+ #
315
+ # Timestamp data types and session time zone are new features in
316
+ # Oracle 9i. This class is available only to fetch or bind <tt>DATE</tt>
317
+ # when using Oracle 8.x client.
318
+ #
319
+ # The retrieved value's time zone is determined not by the session
320
+ # time zone, but by the OCI8::BindType.default_timezone
321
+ # The time zone can be changed as follows:
322
+ #
323
+ # OCI8::BindType.default_timezone = :local
324
+ # # or
325
+ # OCI8::BindType.default_timezone = :utc
326
+ #
327
+ # If you are in the regions where daylight saving time is adopted,
328
+ # you should use OCI8::BindType::Time.
304
329
  #
305
330
  class DateTime
306
331
  if OCI8.oracle_client_version >= ORAVER_9_0
307
- def self.create(con, val, param, max_array_size)
332
+ def self.create(con, val, param, max_array_size) # :nodoc:
308
333
  if true # TODO: check Oracle server version
309
334
  DateTimeViaOCITimestamp.new(con, val, param, max_array_size)
310
335
  else
@@ -312,15 +337,78 @@ class OCI8
312
337
  end
313
338
  end
314
339
  else
315
- def self.create(con, val, param, max_array_size)
340
+ def self.create(con, val, param, max_array_size) # :nodoc:
316
341
  DateTimeViaOCIDate.new(con, val, param, max_array_size)
317
342
  end
318
343
  end
319
344
  end
320
345
 
346
+ #--
347
+ # OCI8::BindType::Time
348
+ #++
349
+ # This is a helper class to select or bind Oracle data types such as
350
+ # <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
351
+ # and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt>. The retrieved value
352
+ # is a \Time.
353
+ #
354
+ # === How to select \Time values.
355
+ #
356
+ # <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
357
+ # and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> are selected as a \Time
358
+ # by default. If the default behaviour is changed, you can select it
359
+ # as a \Time by explicitly calling OCI8::Cursor#define as follows:
360
+ #
361
+ # cursor = conn.parse("SELECT hiredate FROM emp")
362
+ # cursor.define(1, nil, Time)
363
+ # cursor.exec()
364
+ #
365
+ # === Note for ruby prior to 1.9.2
366
+ #
367
+ # If the retrieved value cannot be represented by \Time, it become
368
+ # a \DateTime. The fallback is done only when the ruby is before 1.9.2
369
+ # and one of the following conditions are met.
370
+ # - The timezone part is neither local nor utc.
371
+ # - The time is out of the time_t[http://en.wikipedia.org/wiki/Time_t].
372
+ #
373
+ # If the retrieved value has the precision of fractional second more
374
+ # than 6, the fractional second is truncated to microsecond, which
375
+ # is the precision of standard \Time class.
376
+ #
377
+ # To avoid this fractional second truncation:
378
+ # - Upgrade to ruby 1.9.2, whose \Time precision is nanosecond.
379
+ # - Otherwise, change the defalt mapping to use \DateTime as follows.
380
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::DateTime
381
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::DateTime
382
+ # OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::DateTime
383
+ #
384
+ # === Note for default time zone
385
+ #
386
+ # The retrieved value's time zone is determined by the session time zone
387
+ # if its data type is <tt>DATE</tt>, <tt>TIMESTAMP</tt> or <tt>TIMESTAMP
388
+ # WITH LOCAL TIME ZONE</tt>.
389
+ #
390
+ # The session time zone is same with local machine's by default.
391
+ # It is changed by the following SQL.
392
+ #
393
+ # ALTER SESSION SET TIME_ZONE='-05:00'
394
+ #
395
+ # === Note for Oracle 8.x client
396
+ #
397
+ # Timestamp data types and session time zone are new features in
398
+ # Oracle 9i. This class is available only to fetch or bind <tt>DATE</tt>
399
+ # when using Oracle 8.x client.
400
+ #
401
+ # The retrieved value's time zone is determined not by the session
402
+ # time zone, but by the OCI8::BindType.default_timezone
403
+ # The time zone can be changed as follows:
404
+ #
405
+ # OCI8::BindType.default_timezone = :local
406
+ # # or
407
+ # OCI8::BindType.default_timezone = :utc
408
+ #
321
409
  class Time
322
410
  if OCI8.oracle_client_version >= ORAVER_9_0
323
- def self.create(con, val, param, max_array_size)
411
+ def self.create(con, val, param, max_array_size) # :nodoc:
324
412
  if true # TODO: check Oracle server version
325
413
  TimeViaOCITimestamp.new(con, val, param, max_array_size)
326
414
  else
@@ -328,7 +416,7 @@ class OCI8
328
416
  end
329
417
  end
330
418
  else
331
- def self.create(con, val, param, max_array_size)
419
+ def self.create(con, val, param, max_array_size) # :nodoc:
332
420
  TimeViaOCIDate.new(con, val, param, max_array_size)
333
421
  end
334
422
  end
@@ -339,20 +427,26 @@ class OCI8
339
427
  # OCI8::BindType::IntervalYM
340
428
  #++
341
429
  #
342
- # This is a helper class to bind ruby's
343
- # Integer[http://www.ruby-doc.org/core/classes/Integer.html]
344
- # object as Oracle's <tt>INTERVAL YEAR TO MONTH</tt> datatype.
430
+ # This is a helper class to select or bind Oracle data type
431
+ # <tt>INTERVAL YEAR TO MONTH</tt>. The retrieved value is
432
+ # the number of months between two timestamps.
433
+ #
434
+ # The value can be applied to \DateTime#>> to shift months.
435
+ # It can be applied to \Time#months_since if activisupport has
436
+ # been loaded.
437
+ #
438
+ # === How to select <tt>INTERVAL YEAR TO MONTH</tt>
345
439
  #
346
- # == Select
440
+ # <tt>INTERVAL YEAR TO MONTH</tt> is selected as an Integer.
347
441
  #
348
- # The fetched value for a <tt>INTERVAL YEAR TO MONTH</tt> column
349
- # is an Integer[http://www.ruby-doc.org/core/classes/Integer.html]
350
- # which means the months between two timestamps.
442
+ # conn.exec("select (current_timestamp - hiredate) year to month from emp") do |hired_months|
443
+ # puts "hired_months = #{hired_months}"
444
+ # end
351
445
  #
352
- # == Bind
446
+ # == How to bind <tt>INTERVAL YEAR TO MONTH</tt>
353
447
  #
354
- # You cannot bind as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
355
- # It must be bound explicitly with :interval_ym.
448
+ # You cannot bind a bind variable as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
449
+ # It must be bound explicitly by OCI8::Cursor#bind_param.
356
450
  #
357
451
  # # output bind variable
358
452
  # cursor = conn.parse(<<-EOS)
@@ -399,51 +493,43 @@ class OCI8
399
493
  # OCI8::BindType::IntervalDS
400
494
  #++
401
495
  #
402
- # This is a helper class to bind ruby's
403
- # Rational[http://www.ruby-doc.org/core/classes/Rational.html]
404
- # object as Oracle's <tt>INTERVAL DAY TO SECOND</tt> datatype.
496
+ # (new in 2.0)
405
497
  #
406
- # == Select
498
+ # This is a helper class to select or bind Oracle data type
499
+ # <tt>INTERVAL DAY TO SECOND</tt>. The retrieved value is
500
+ # the number of seconds between two typestamps as a \Float.
407
501
  #
408
- # The fetched value for a <tt>INTERVAL DAY TO SECOND</tt> column
409
- # is a Rational[http://www.ruby-doc.org/core/classes/Rational.html]
410
- # or an Integer[http://www.ruby-doc.org/core/classes/Integer.html].
411
- # The value is usable to apply to
412
- # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#+ and
413
- # DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#-.
502
+ # Note that it is the number days as a \Rational if
503
+ # OCI8::BindType::IntervalDS.unit is :day or the ruby-oci8
504
+ # version is prior to 2.0.3.
414
505
  #
415
- # == Bind
506
+ # == How to bind <tt>INTERVAL DAY TO SECOND</tt>
416
507
  #
417
- # You cannot bind as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
418
- # It must be bound explicitly with :interval_ds.
508
+ # You cannot bind a bind variable as <tt>INTERVAL DAY TO SECOND</tt>
509
+ # implicitly. It must be bound explicitly by OCI8::Cursor#bind_param.
419
510
  #
420
- # # output
421
- # ts1 = DateTime.parse('1969-11-19 06:54:35 00:00')
422
- # ts2 = DateTime.parse('1969-07-20 20:17:40 00:00')
511
+ # # output bind variable
423
512
  # cursor = conn.parse(<<-EOS)
424
513
  # BEGIN
425
- # :itv := (:ts1 - :ts2) DAY TO SECOND;
514
+ # :interval := (:ts1 - :ts2) DAY TO SECOND(9);
426
515
  # END;
427
516
  # EOS
428
- # cursor.bind_param(:itv, nil, :interval_ds)
429
- # cursor.bind_param(:ts1, ts1)
430
- # cursor.bind_param(:ts2, ts2)
517
+ # cursor.bind_param(:interval, nil, :interval_ds)
518
+ # cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
519
+ # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
431
520
  # cursor.exec
432
- # cursor[:itv] # == ts1 - ts2
521
+ # cursor[:interval] # => 10492615.0 seconds
433
522
  # cursor.close
434
523
  #
435
- # # input
436
- # ts2 = DateTime.parse('1969-07-20 20:17:40 00:00')
437
- # itv = 121 + 10.to_r/24 + 36.to_r/(24*60) + 55.to_r/(24*60*60)
438
- # # 121 days, 10 hours, 36 minutes, 55 seconds
524
+ # # input bind variable
439
525
  # cursor = conn.parse(<<-EOS)
440
526
  # BEGIN
441
- # :ts1 := :ts2 + :itv;
527
+ # :ts1 := :ts2 + :interval;
442
528
  # END;
443
529
  # EOS
444
530
  # cursor.bind_param(:ts1, nil, DateTime)
445
- # cursor.bind_param(:ts2, ts2)
446
- # cursor.bind_param(:itv, itv, :interval_ds)
531
+ # cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
532
+ # cursor.bind_param(:interval, 10492615.0, :interval_ds)
447
533
  # cursor.exec
448
534
  # cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35
449
535
  # cursor.close
@@ -453,6 +539,32 @@ class OCI8
453
539
  @@minute = @@hour / 60
454
540
  @@sec = @@minute / 60
455
541
  @@fsec = @@sec / 1000000000
542
+ @@unit = :second
543
+
544
+ # call-seq:
545
+ # OCI8::BindType::IntervalDS.unit -> :second or :day
546
+ #
547
+ # (new in 2.0.3)
548
+ #
549
+ # Retrieves the unit of interval.
550
+ def self.unit
551
+ @@unit
552
+ end
553
+
554
+ # call-seq:
555
+ # OCI8::BindType::IntervalDS.unit = :second or :day
556
+ #
557
+ # (new in 2.0.3)
558
+ #
559
+ # Changes the unit of interval. :second is the default.
560
+ def self.unit=(val)
561
+ case val
562
+ when :second, :day
563
+ @@unit = val
564
+ else
565
+ raise 'unit should be :second or :day'
566
+ end
567
+ end
456
568
 
457
569
  def set(val) # :nodoc:
458
570
  unless val.nil?
@@ -462,10 +574,17 @@ class OCI8
462
574
  else
463
575
  is_minus = false
464
576
  end
465
- day, val = val.divmod 1
466
- hour, val = (val * 24).divmod 1
467
- minute, val = (val * 60).divmod 1
468
- sec, val = (val * 60).divmod 1
577
+ if @@unit == :second
578
+ day, val = val.divmod 86400
579
+ hour, val = val.divmod 3600
580
+ minute, val = val.divmod 60
581
+ sec, val = val.divmod 1
582
+ else
583
+ day, val = val.divmod 1
584
+ hour, val = (val * 24).divmod 1
585
+ minute, val = (val * 60).divmod 1
586
+ sec, val = (val * 60).divmod 1
587
+ end
469
588
  fsec, val = (val * 1000000000).divmod 1
470
589
  if is_minus
471
590
  day = - day
@@ -483,7 +602,12 @@ class OCI8
483
602
  val = super()
484
603
  return nil if val.nil?
485
604
  day, hour, minute, sec, fsec = val
486
- day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
605
+ if @@unit == :second
606
+ fsec = fsec / 1000000000.0
607
+ day * 86400 + hour * 3600 + minute * 60 + sec + fsec
608
+ else
609
+ day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
610
+ end
487
611
  end
488
612
  end # OCI8::BindType::IntervalDS
489
613
  end