ruby-oci8 2.1.5.1-x64-mingw32
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.
- checksums.yaml +7 -0
- data/.yardopts +17 -0
- data/COPYING +30 -0
- data/COPYING_old +64 -0
- data/ChangeLog +2779 -0
- data/Makefile +92 -0
- data/NEWS +660 -0
- data/README.md +43 -0
- data/VERSION +1 -0
- data/dist-files +91 -0
- data/docs/install-binary-package.md +40 -0
- data/docs/install-full-client.md +116 -0
- data/docs/install-instant-client.md +167 -0
- data/docs/platform-specific-issues.md +197 -0
- data/docs/report-installation-issue.md +50 -0
- data/lib/.document +1 -0
- data/lib/dbd/OCI8.rb +591 -0
- data/lib/oci8.rb +147 -0
- data/lib/oci8.rb.in +147 -0
- data/lib/oci8/.document +8 -0
- data/lib/oci8/bindtype.rb +350 -0
- data/lib/oci8/compat.rb +113 -0
- data/lib/oci8/connection_pool.rb +108 -0
- data/lib/oci8/cursor.rb +564 -0
- data/lib/oci8/datetime.rb +605 -0
- data/lib/oci8/encoding-init.rb +79 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2092 -0
- data/lib/oci8/object.rb +605 -0
- data/lib/oci8/oci8.rb +560 -0
- data/lib/oci8/ocihandle.rb +607 -0
- data/lib/oci8/oracle_version.rb +143 -0
- data/lib/oci8/properties.rb +134 -0
- data/lib/oci8lib_200.so +0 -0
- data/metaconfig +142 -0
- data/pre-distclean.rb +7 -0
- data/ruby-oci8.gemspec +80 -0
- data/setup.rb +1333 -0
- data/test/README +42 -0
- data/test/config.rb +184 -0
- data/test/setup_test_object.sql +171 -0
- data/test/test_all.rb +54 -0
- data/test/test_appinfo.rb +63 -0
- data/test/test_array_dml.rb +333 -0
- data/test/test_bind_raw.rb +46 -0
- data/test/test_bind_string.rb +106 -0
- data/test/test_bind_time.rb +178 -0
- data/test/test_break.rb +124 -0
- data/test/test_clob.rb +98 -0
- data/test/test_connection_pool.rb +125 -0
- data/test/test_connstr.rb +81 -0
- data/test/test_datetime.rb +581 -0
- data/test/test_dbi.rb +366 -0
- data/test/test_dbi_clob.rb +53 -0
- data/test/test_encoding.rb +104 -0
- data/test/test_error.rb +88 -0
- data/test/test_metadata.rb +1485 -0
- data/test/test_object.rb +462 -0
- data/test/test_oci8.rb +489 -0
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +256 -0
- data/test/test_oranumber.rb +787 -0
- data/test/test_rowid.rb +33 -0
- metadata +109 -0
@@ -0,0 +1,605 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class OCI8
|
4
|
+
|
5
|
+
module BindType
|
6
|
+
|
7
|
+
# Returns the default time zone when using Oracle 8.x client.
|
8
|
+
# The value is unused when using Oracle 9i or upper client.
|
9
|
+
#
|
10
|
+
# See also: OCI8::BindType::Time
|
11
|
+
#
|
12
|
+
# @return [:local or :utc]
|
13
|
+
def self.default_timezone
|
14
|
+
OCI8::BindType::Util.default_timezone
|
15
|
+
end
|
16
|
+
|
17
|
+
# Sets the default time zone when using Oracle 8.x client.
|
18
|
+
# The value is unused when using Oracle 9i or upper client.
|
19
|
+
#
|
20
|
+
# See also: OCI8::BindType::Time
|
21
|
+
#
|
22
|
+
# @param [:local or :utc] tz
|
23
|
+
def self.default_timezone=(tz)
|
24
|
+
OCI8::BindType::Util.default_timezone = tz
|
25
|
+
end
|
26
|
+
|
27
|
+
module Util # :nodoc:
|
28
|
+
|
29
|
+
@@datetime_fsec_base = (1 / ::DateTime.parse('0001-01-01 00:00:00.000000001').sec_fraction).to_i
|
30
|
+
|
31
|
+
@@default_timezone = :local
|
32
|
+
begin
|
33
|
+
Time.new(2001, 1, 1, 0, 0, 0, '+00:00')
|
34
|
+
@@time_new_accepts_timezone = true # after ruby 1.9.2
|
35
|
+
rescue ArgumentError
|
36
|
+
@@time_new_accepts_timezone = false # prior to ruby 1.9.2
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
# 2001-01-01 00:00:59.999
|
41
|
+
::DateTime.civil(2001, 1, 1, 0, 0, Rational(59_999, 1000), 0)
|
42
|
+
@@datetime_has_fractional_second_bug = false
|
43
|
+
rescue ArgumentError
|
44
|
+
@@datetime_has_fractional_second_bug = true
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.default_timezone
|
48
|
+
@@default_timezone
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.default_timezone=(tz)
|
52
|
+
if tz != :local and tz != :utc
|
53
|
+
raise ArgumentError, "expected :local or :utc but #{tz}"
|
54
|
+
end
|
55
|
+
@@default_timezone = tz
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def datetime_to_array(val, datatype)
|
61
|
+
return nil if val.nil?
|
62
|
+
|
63
|
+
# year
|
64
|
+
year = val.year
|
65
|
+
# month
|
66
|
+
if val.respond_to? :mon
|
67
|
+
month = val.mon
|
68
|
+
elsif val.respond_to? :month
|
69
|
+
month = val.month
|
70
|
+
else
|
71
|
+
raise "expect Time, Date or DateTime but #{val.class}"
|
72
|
+
end
|
73
|
+
# day
|
74
|
+
if val.respond_to? :mday
|
75
|
+
day = val.mday
|
76
|
+
elsif val.respond_to? :day
|
77
|
+
day = val.day
|
78
|
+
else
|
79
|
+
raise "expect Time, Date or DateTime but #{val.class}"
|
80
|
+
end
|
81
|
+
# hour
|
82
|
+
if val.respond_to? :hour
|
83
|
+
hour = val.hour
|
84
|
+
else
|
85
|
+
hour = 0
|
86
|
+
end
|
87
|
+
# minute
|
88
|
+
if val.respond_to? :min
|
89
|
+
minute = val.min
|
90
|
+
else
|
91
|
+
minute = 0
|
92
|
+
end
|
93
|
+
# second
|
94
|
+
if val.respond_to? :sec
|
95
|
+
sec = val.sec
|
96
|
+
else
|
97
|
+
sec = 0
|
98
|
+
end
|
99
|
+
return [year, month, day, hour, minute, sec] if datatype == :date
|
100
|
+
|
101
|
+
# fractional second
|
102
|
+
if val.respond_to? :sec_fraction
|
103
|
+
fsec = (val.sec_fraction * @@datetime_fsec_base).to_i
|
104
|
+
elsif val.respond_to? :nsec
|
105
|
+
fsec = val.nsec
|
106
|
+
elsif val.respond_to? :usec
|
107
|
+
fsec = val.usec * 1000
|
108
|
+
else
|
109
|
+
fsec = 0
|
110
|
+
end
|
111
|
+
return [year, month, day, hour, minute, sec, fsec, nil, nil] if datatype == :timestamp
|
112
|
+
|
113
|
+
# time zone
|
114
|
+
if val.respond_to? :offset
|
115
|
+
# DateTime
|
116
|
+
tz_min = (val.offset * 1440).to_i
|
117
|
+
elsif val.respond_to? :utc_offset
|
118
|
+
# Time
|
119
|
+
tz_min = val.utc_offset / 60
|
120
|
+
else
|
121
|
+
tz_hour = nil
|
122
|
+
tz_min = nil
|
123
|
+
end
|
124
|
+
if tz_min
|
125
|
+
if tz_min < 0
|
126
|
+
tz_min = - tz_min
|
127
|
+
tz_hour = - (tz_min / 60)
|
128
|
+
tz_min = (tz_min % 60)
|
129
|
+
else
|
130
|
+
tz_hour = tz_min / 60
|
131
|
+
tz_min = tz_min % 60
|
132
|
+
end
|
133
|
+
end
|
134
|
+
[year, month, day, hour, minute, sec, fsec, tz_hour, tz_min]
|
135
|
+
end
|
136
|
+
|
137
|
+
def array_to_datetime(ary, timezone)
|
138
|
+
return nil if ary.nil?
|
139
|
+
|
140
|
+
year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
|
141
|
+
sec += nsec.to_r / 1000000000 if nsec and nsec != 0
|
142
|
+
if tz_hour and tz_min
|
143
|
+
offset = tz_hour.to_r / 24 + tz_min.to_r / 1440
|
144
|
+
else
|
145
|
+
if @@default_timezone == :local
|
146
|
+
if ::DateTime.respond_to? :local_offset
|
147
|
+
offset = ::DateTime.local_offset # Use a method defined by active support.
|
148
|
+
else
|
149
|
+
# Do as active support does.
|
150
|
+
offset = ::Time.local(2007).utc_offset.to_r / 86400
|
151
|
+
end
|
152
|
+
else
|
153
|
+
offset = 0
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
if @@datetime_has_fractional_second_bug and sec >= 59 and nsec != 0
|
158
|
+
# convert to a DateTime via a String as a workaround
|
159
|
+
if offset >= 0
|
160
|
+
sign = ?+
|
161
|
+
else
|
162
|
+
sign = ?-
|
163
|
+
offset = - offset;
|
164
|
+
end
|
165
|
+
tz_min = (offset * 1440).to_i
|
166
|
+
tz_hour, tz_min = tz_min.divmod 60
|
167
|
+
time_str = format("%04d-%02d-%02dT%02d:%02d:%02d.%09d%c%02d:%02d",
|
168
|
+
year, month, day, hour, minute, sec, nsec, sign, tz_hour, tz_min)
|
169
|
+
::DateTime.parse(time_str)
|
170
|
+
else
|
171
|
+
::DateTime.civil(year, month, day, hour, minute, sec, offset)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
if @@time_new_accepts_timezone
|
176
|
+
|
177
|
+
# after ruby 1.9.2
|
178
|
+
def array_to_time(ary, timezone)
|
179
|
+
return nil if ary.nil?
|
180
|
+
|
181
|
+
year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
|
182
|
+
nsec ||= 0
|
183
|
+
|
184
|
+
if timezone
|
185
|
+
usec = (nsec == 0) ? 0 : nsec.to_r / 1000
|
186
|
+
::Time.send(timezone, year, month, day, hour, minute, sec, usec)
|
187
|
+
else
|
188
|
+
sec += nsec.to_r / 1_000_000_000 if nsec != 0
|
189
|
+
utc_offset = tz_hour * 3600 + tz_min * 60
|
190
|
+
::Time.new(year, month, day, hour, minute, sec, utc_offset)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
else
|
195
|
+
|
196
|
+
# prior to ruby 1.9.2
|
197
|
+
def array_to_time(ary, timezone)
|
198
|
+
return nil if ary.nil?
|
199
|
+
|
200
|
+
year, month, day, hour, minute, sec, nsec, tz_hour, tz_min = ary
|
201
|
+
nsec ||= 0
|
202
|
+
usec = (nsec == 0) ? 0 : nsec.to_r / 1000
|
203
|
+
begin
|
204
|
+
if timezone
|
205
|
+
return ::Time.send(timezone, year, month, day, hour, minute, sec, usec)
|
206
|
+
else
|
207
|
+
if tz_hour == 0 and tz_min == 0
|
208
|
+
tm = ::Time.utc(year, month, day, hour, minute, sec, usec)
|
209
|
+
# Time.utc(99, ...) returns a time object the year of which is 1999.
|
210
|
+
# 'tm.year == year' checks such cases.
|
211
|
+
return tm if tm.year == year
|
212
|
+
else
|
213
|
+
tm = ::Time.local(year, month, day, hour, minute, sec, usec)
|
214
|
+
return tm if tm.utc_offset == tz_hour * 3600 + tz_min * 60 and tm.year == year
|
215
|
+
end
|
216
|
+
end
|
217
|
+
rescue StandardError
|
218
|
+
end
|
219
|
+
array_to_datetime(ary, timezone)
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
#--
|
226
|
+
# OCI8::BindType::DateTime
|
227
|
+
#++
|
228
|
+
# This is a helper class to select or bind Oracle data types such as
|
229
|
+
# <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
|
230
|
+
# and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt>. The retrieved value
|
231
|
+
# is a \DateTime.
|
232
|
+
#
|
233
|
+
# === How to select \DataTime values.
|
234
|
+
#
|
235
|
+
# <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
|
236
|
+
# and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> are selected as a \Time
|
237
|
+
# by default. You change the behaviour by explicitly calling
|
238
|
+
# OCI8::Cursor#define as follows:
|
239
|
+
#
|
240
|
+
# cursor = conn.parse("SELECT hiredate FROM emp")
|
241
|
+
# cursor.define(1, nil, DateTime)
|
242
|
+
# cursor.exec()
|
243
|
+
#
|
244
|
+
# Otherwise, you can change the default mapping for all queries.
|
245
|
+
#
|
246
|
+
# # Changes the mapping for DATE
|
247
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_DAT] = OCI8::BindType::DateTime
|
248
|
+
#
|
249
|
+
# # Changes the mapping for TIMESTAMP
|
250
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::DateTime
|
251
|
+
#
|
252
|
+
# # Changes the mapping for TIMESTAMP WITH TIME ZONE
|
253
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::DateTime
|
254
|
+
#
|
255
|
+
# # Changes the mapping for TIMESTAMP WITH LOCAL TIME ZONE
|
256
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::DateTime
|
257
|
+
#
|
258
|
+
# === Note for default time zone
|
259
|
+
#
|
260
|
+
# The retrieved value's time zone is determined by the session time zone
|
261
|
+
# if its data type is <tt>DATE</tt>, <tt>TIMESTAMP</tt> or <tt>TIMESTAMP
|
262
|
+
# WITH LOCAL TIME ZONE</tt>.
|
263
|
+
#
|
264
|
+
# The session time zone is same with local machine's by default.
|
265
|
+
# It is changed by the following SQL.
|
266
|
+
#
|
267
|
+
# ALTER SESSION SET TIME_ZONE='-05:00'
|
268
|
+
#
|
269
|
+
# === Note for Oracle 8.x client
|
270
|
+
#
|
271
|
+
# Timestamp data types and session time zone are new features in
|
272
|
+
# Oracle 9i. This class is available only to fetch or bind <tt>DATE</tt>
|
273
|
+
# when using Oracle 8.x client.
|
274
|
+
#
|
275
|
+
# The retrieved value's time zone is determined not by the session
|
276
|
+
# time zone, but by the OCI8::BindType.default_timezone
|
277
|
+
# The time zone can be changed as follows:
|
278
|
+
#
|
279
|
+
# OCI8::BindType.default_timezone = :local
|
280
|
+
# # or
|
281
|
+
# OCI8::BindType.default_timezone = :utc
|
282
|
+
#
|
283
|
+
# If you are in the regions where daylight saving time is adopted,
|
284
|
+
# you should use OCI8::BindType::Time.
|
285
|
+
#
|
286
|
+
class DateTime < OCI8::BindType::OCITimestampTZ
|
287
|
+
include OCI8::BindType::Util
|
288
|
+
|
289
|
+
def set(val) # :nodoc:
|
290
|
+
super(datetime_to_array(val, :timestamp_tz))
|
291
|
+
end
|
292
|
+
|
293
|
+
def get() # :nodoc:
|
294
|
+
array_to_datetime(super(), nil)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class LocalDateTime < OCI8::BindType::OCITimestamp
|
299
|
+
include OCI8::BindType::Util
|
300
|
+
|
301
|
+
def set(val) # :nodoc:
|
302
|
+
super(datetime_to_array(val, :timestamp))
|
303
|
+
end
|
304
|
+
|
305
|
+
def get() # :nodoc:
|
306
|
+
array_to_datetime(super(), :local)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
class UTCDateTime < OCI8::BindType::OCITimestamp
|
311
|
+
include OCI8::BindType::Util
|
312
|
+
|
313
|
+
def set(val) # :nodoc:
|
314
|
+
super(datetime_to_array(val, :timestamp))
|
315
|
+
end
|
316
|
+
|
317
|
+
def get() # :nodoc:
|
318
|
+
array_to_datetime(super(), :utc)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
#--
|
323
|
+
# OCI8::BindType::Time
|
324
|
+
#++
|
325
|
+
# This is a helper class to select or bind Oracle data types such as
|
326
|
+
# <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
|
327
|
+
# and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt>. The retrieved value
|
328
|
+
# is a \Time.
|
329
|
+
#
|
330
|
+
# === How to select \Time values.
|
331
|
+
#
|
332
|
+
# <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH TIME ZONE</tt>
|
333
|
+
# and <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> are selected as a \Time
|
334
|
+
# by default. If the default behaviour is changed, you can select it
|
335
|
+
# as a \Time by explicitly calling OCI8::Cursor#define as follows:
|
336
|
+
#
|
337
|
+
# cursor = conn.parse("SELECT hiredate FROM emp")
|
338
|
+
# cursor.define(1, nil, Time)
|
339
|
+
# cursor.exec()
|
340
|
+
#
|
341
|
+
# === Note for ruby prior to 1.9.2
|
342
|
+
#
|
343
|
+
# If the retrieved value cannot be represented by \Time, it become
|
344
|
+
# a \DateTime. The fallback is done only when the ruby is before 1.9.2
|
345
|
+
# and one of the following conditions are met.
|
346
|
+
# - The timezone part is neither local nor utc.
|
347
|
+
# - The time is out of the time_t[http://en.wikipedia.org/wiki/Time_t].
|
348
|
+
#
|
349
|
+
# If the retrieved value has the precision of fractional second more
|
350
|
+
# than 6, the fractional second is truncated to microsecond, which
|
351
|
+
# is the precision of standard \Time class.
|
352
|
+
#
|
353
|
+
# To avoid this fractional second truncation:
|
354
|
+
# - Upgrade to ruby 1.9.2, whose \Time precision is nanosecond.
|
355
|
+
# - Otherwise, change the defalt mapping to use \DateTime as follows.
|
356
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP] = OCI8::BindType::DateTime
|
357
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_TZ] = OCI8::BindType::DateTime
|
358
|
+
# OCI8::BindType::Mapping[OCI8::SQLT_TIMESTAMP_LTZ] = OCI8::BindType::DateTime
|
359
|
+
#
|
360
|
+
# === Note for default time zone
|
361
|
+
#
|
362
|
+
# The retrieved value's time zone is determined by the session time zone
|
363
|
+
# if its data type is <tt>DATE</tt>, <tt>TIMESTAMP</tt> or <tt>TIMESTAMP
|
364
|
+
# WITH LOCAL TIME ZONE</tt>.
|
365
|
+
#
|
366
|
+
# The session time zone is same with local machine's by default.
|
367
|
+
# It is changed by the following SQL.
|
368
|
+
#
|
369
|
+
# ALTER SESSION SET TIME_ZONE='-05:00'
|
370
|
+
#
|
371
|
+
# === Note for Oracle 8.x client
|
372
|
+
#
|
373
|
+
# Timestamp data types and session time zone are new features in
|
374
|
+
# Oracle 9i. This class is available only to fetch or bind <tt>DATE</tt>
|
375
|
+
# when using Oracle 8.x client.
|
376
|
+
#
|
377
|
+
# The retrieved value's time zone is determined not by the session
|
378
|
+
# time zone, but by the OCI8::BindType.default_timezone
|
379
|
+
# The time zone can be changed as follows:
|
380
|
+
#
|
381
|
+
# OCI8::BindType.default_timezone = :local
|
382
|
+
# # or
|
383
|
+
# OCI8::BindType.default_timezone = :utc
|
384
|
+
#
|
385
|
+
class Time < OCI8::BindType::OCITimestampTZ
|
386
|
+
include OCI8::BindType::Util
|
387
|
+
|
388
|
+
def set(val) # :nodoc:
|
389
|
+
super(datetime_to_array(val, :timestamp_tz))
|
390
|
+
end
|
391
|
+
|
392
|
+
def get() # :nodoc:
|
393
|
+
array_to_time(super(), nil)
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
class LocalTime < OCI8::BindType::OCITimestamp
|
398
|
+
include OCI8::BindType::Util
|
399
|
+
|
400
|
+
def set(val) # :nodoc:
|
401
|
+
super(datetime_to_array(val, :timestamp))
|
402
|
+
end
|
403
|
+
|
404
|
+
def get() # :nodoc:
|
405
|
+
array_to_time(super(), :local)
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
class UTCTime < OCI8::BindType::OCITimestamp
|
410
|
+
include OCI8::BindType::Util
|
411
|
+
|
412
|
+
def set(val) # :nodoc:
|
413
|
+
super(datetime_to_array(val, :timestamp))
|
414
|
+
end
|
415
|
+
|
416
|
+
def get() # :nodoc:
|
417
|
+
array_to_time(super(), :utc)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
#--
|
422
|
+
# OCI8::BindType::IntervalYM
|
423
|
+
#++
|
424
|
+
#
|
425
|
+
# This is a helper class to select or bind Oracle data type
|
426
|
+
# <tt>INTERVAL YEAR TO MONTH</tt>. The retrieved value is
|
427
|
+
# the number of months between two timestamps.
|
428
|
+
#
|
429
|
+
# The value can be applied to \DateTime#>> to shift months.
|
430
|
+
# It can be applied to \Time#months_since if activisupport has
|
431
|
+
# been loaded.
|
432
|
+
#
|
433
|
+
# === How to select <tt>INTERVAL YEAR TO MONTH</tt>
|
434
|
+
#
|
435
|
+
# <tt>INTERVAL YEAR TO MONTH</tt> is selected as an Integer.
|
436
|
+
#
|
437
|
+
# conn.exec("select (current_timestamp - hiredate) year to month from emp") do |hired_months|
|
438
|
+
# puts "hired_months = #{hired_months}"
|
439
|
+
# end
|
440
|
+
#
|
441
|
+
# == How to bind <tt>INTERVAL YEAR TO MONTH</tt>
|
442
|
+
#
|
443
|
+
# You cannot bind a bind variable as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
|
444
|
+
# It must be bound explicitly by OCI8::Cursor#bind_param.
|
445
|
+
#
|
446
|
+
# # output bind variable
|
447
|
+
# cursor = conn.parse(<<-EOS)
|
448
|
+
# BEGIN
|
449
|
+
# :interval := (:ts1 - :ts2) YEAR TO MONTH;
|
450
|
+
# END;
|
451
|
+
# EOS
|
452
|
+
# cursor.bind_param(:interval, nil, :interval_ym)
|
453
|
+
# cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
|
454
|
+
# cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
|
455
|
+
# cursor.exec
|
456
|
+
# cursor[:interval] # => 4 (months)
|
457
|
+
# cursor.close
|
458
|
+
#
|
459
|
+
# # input bind variable
|
460
|
+
# cursor = conn.parse(<<-EOS)
|
461
|
+
# BEGIN
|
462
|
+
# :ts1 := :ts2 + :interval;
|
463
|
+
# END;
|
464
|
+
# EOS
|
465
|
+
# cursor.bind_param(:ts1, nil, DateTime)
|
466
|
+
# cursor.bind_param(:ts2, Date.parse('1969-11-19'))
|
467
|
+
# cursor.bind_param(:interval, 4, :interval_ym)
|
468
|
+
# cursor.exec
|
469
|
+
# cursor[:ts1].strftime('%Y-%m-%d') # => 1970-03-19
|
470
|
+
# cursor.close
|
471
|
+
#
|
472
|
+
class IntervalYM < OCI8::BindType::OCIIntervalYM
|
473
|
+
def set(val) # :nodoc:
|
474
|
+
unless val.nil?
|
475
|
+
val = [val / 12, val % 12]
|
476
|
+
end
|
477
|
+
super(val)
|
478
|
+
end
|
479
|
+
def get() # :nodoc:
|
480
|
+
val = super()
|
481
|
+
return nil if val.nil?
|
482
|
+
year, month = val
|
483
|
+
year * 12 + month
|
484
|
+
end
|
485
|
+
end # OCI8::BindType::IntervalYM
|
486
|
+
|
487
|
+
#--
|
488
|
+
# OCI8::BindType::IntervalDS
|
489
|
+
#++
|
490
|
+
#
|
491
|
+
# (new in 2.0)
|
492
|
+
#
|
493
|
+
# This is a helper class to select or bind Oracle data type
|
494
|
+
# <tt>INTERVAL DAY TO SECOND</tt>. The retrieved value is
|
495
|
+
# the number of seconds between two typestamps as a \Float.
|
496
|
+
#
|
497
|
+
# Note that it is the number days as a \Rational if
|
498
|
+
# OCI8::BindType::IntervalDS.unit is :day or the ruby-oci8
|
499
|
+
# version is prior to 2.0.3.
|
500
|
+
#
|
501
|
+
# == How to bind <tt>INTERVAL DAY TO SECOND</tt>
|
502
|
+
#
|
503
|
+
# You cannot bind a bind variable as <tt>INTERVAL DAY TO SECOND</tt>
|
504
|
+
# implicitly. It must be bound explicitly by OCI8::Cursor#bind_param.
|
505
|
+
#
|
506
|
+
# # output bind variable
|
507
|
+
# cursor = conn.parse(<<-EOS)
|
508
|
+
# BEGIN
|
509
|
+
# :interval := (:ts1 - :ts2) DAY TO SECOND(9);
|
510
|
+
# END;
|
511
|
+
# EOS
|
512
|
+
# cursor.bind_param(:interval, nil, :interval_ds)
|
513
|
+
# cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
|
514
|
+
# cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
|
515
|
+
# cursor.exec
|
516
|
+
# cursor[:interval] # => 10492615.0 seconds
|
517
|
+
# cursor.close
|
518
|
+
#
|
519
|
+
# # input bind variable
|
520
|
+
# cursor = conn.parse(<<-EOS)
|
521
|
+
# BEGIN
|
522
|
+
# :ts1 := :ts2 + :interval;
|
523
|
+
# END;
|
524
|
+
# EOS
|
525
|
+
# cursor.bind_param(:ts1, nil, DateTime)
|
526
|
+
# cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
|
527
|
+
# cursor.bind_param(:interval, 10492615.0, :interval_ds)
|
528
|
+
# cursor.exec
|
529
|
+
# cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35
|
530
|
+
# cursor.close
|
531
|
+
#
|
532
|
+
class IntervalDS < OCI8::BindType::OCIIntervalDS
|
533
|
+
@@hour = 1 / 24.to_r
|
534
|
+
@@minute = @@hour / 60
|
535
|
+
@@sec = @@minute / 60
|
536
|
+
@@fsec = @@sec / 1000000000
|
537
|
+
@@unit = :second
|
538
|
+
|
539
|
+
# Retrieves the unit of interval.
|
540
|
+
#
|
541
|
+
# @return [:second or :day]
|
542
|
+
# @since 2.0.3
|
543
|
+
def self.unit
|
544
|
+
@@unit
|
545
|
+
end
|
546
|
+
|
547
|
+
# Changes the unit of interval. :second is the default.
|
548
|
+
#
|
549
|
+
# @param [:second or :day] val
|
550
|
+
# @since 2.0.3
|
551
|
+
def self.unit=(val)
|
552
|
+
case val
|
553
|
+
when :second, :day
|
554
|
+
@@unit = val
|
555
|
+
else
|
556
|
+
raise 'unit should be :second or :day'
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def set(val) # :nodoc:
|
561
|
+
unless val.nil?
|
562
|
+
if val < 0
|
563
|
+
is_minus = true
|
564
|
+
val = -val
|
565
|
+
else
|
566
|
+
is_minus = false
|
567
|
+
end
|
568
|
+
if @@unit == :second
|
569
|
+
day, val = val.divmod 86400
|
570
|
+
hour, val = val.divmod 3600
|
571
|
+
minute, val = val.divmod 60
|
572
|
+
sec, val = val.divmod 1
|
573
|
+
else
|
574
|
+
day, val = val.divmod 1
|
575
|
+
hour, val = (val * 24).divmod 1
|
576
|
+
minute, val = (val * 60).divmod 1
|
577
|
+
sec, val = (val * 60).divmod 1
|
578
|
+
end
|
579
|
+
fsec, val = (val * 1000000000).divmod 1
|
580
|
+
if is_minus
|
581
|
+
day = - day
|
582
|
+
hour = - hour
|
583
|
+
minute = - minute
|
584
|
+
sec = - sec
|
585
|
+
fsec = - fsec
|
586
|
+
end
|
587
|
+
val = [day, hour, minute, sec, fsec]
|
588
|
+
end
|
589
|
+
super(val)
|
590
|
+
end
|
591
|
+
|
592
|
+
def get() # :nodoc:
|
593
|
+
val = super()
|
594
|
+
return nil if val.nil?
|
595
|
+
day, hour, minute, sec, fsec = val
|
596
|
+
if @@unit == :second
|
597
|
+
fsec = fsec / 1000000000.0
|
598
|
+
day * 86400 + hour * 3600 + minute * 60 + sec + fsec
|
599
|
+
else
|
600
|
+
day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
|
601
|
+
end
|
602
|
+
end
|
603
|
+
end # OCI8::BindType::IntervalDS
|
604
|
+
end # OCI8::BindType
|
605
|
+
end # OCI8
|