ruby-oci8 1.0.7 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +1254 -390
- data/Makefile +10 -13
- data/README +56 -385
- data/VERSION +1 -1
- data/dist-files +26 -27
- data/ext/oci8/.document +1 -0
- data/ext/oci8/MANIFEST +0 -4
- data/ext/oci8/apiwrap.c.tmpl +172 -0
- data/ext/oci8/apiwrap.h.tmpl +61 -0
- data/ext/oci8/apiwrap.rb +91 -0
- data/ext/oci8/apiwrap.yml +1243 -0
- data/ext/oci8/attr.c +124 -384
- data/ext/oci8/bind.c +472 -164
- data/ext/oci8/encoding.c +196 -0
- data/ext/oci8/env.c +84 -253
- data/ext/oci8/error.c +196 -127
- data/ext/oci8/extconf.rb +82 -59
- data/ext/oci8/lob.c +710 -370
- data/ext/oci8/metadata.c +359 -0
- data/ext/oci8/object.c +622 -0
- data/ext/oci8/oci8.c +577 -161
- data/ext/oci8/oci8.h +354 -258
- data/ext/oci8/oci8lib.c +493 -0
- data/ext/oci8/ocidatetime.c +473 -0
- data/ext/oci8/ocinumber.c +1123 -24
- data/ext/oci8/oraconf.rb +72 -106
- data/ext/oci8/oradate.c +511 -321
- data/ext/oci8/stmt.c +752 -572
- data/ext/oci8/win32.c +131 -0
- data/ext/oci8/xmldb.c +383 -0
- data/lib/.document +2 -0
- data/lib/dbd/OCI8.rb +2 -17
- data/lib/oci8.rb.in +41 -1622
- data/lib/oci8/.document +5 -0
- data/lib/oci8/compat.rb +108 -0
- data/lib/oci8/datetime.rb +489 -0
- data/lib/oci8/encoding-init.rb +40 -0
- data/lib/oci8/encoding.yml +537 -0
- data/lib/oci8/metadata.rb +2077 -0
- data/lib/oci8/object.rb +548 -0
- data/lib/oci8/oci8.rb +773 -0
- data/lib/oci8/oracle_version.rb +144 -0
- data/metaconfig +3 -3
- data/ruby-oci8.gemspec +5 -5
- data/setup.rb +4 -4
- data/test/config.rb +64 -84
- data/test/test_all.rb +14 -21
- data/test/test_array_dml.rb +317 -0
- data/test/test_bind_raw.rb +18 -25
- data/test/test_bind_time.rb +78 -91
- data/test/test_break.rb +37 -35
- data/test/test_clob.rb +33 -89
- data/test/test_connstr.rb +5 -4
- data/test/test_datetime.rb +469 -0
- data/test/test_dbi.rb +99 -60
- data/test/test_dbi_clob.rb +3 -8
- data/test/test_metadata.rb +65 -51
- data/test/test_oci8.rb +151 -55
- data/test/test_oracle_version.rb +70 -0
- data/test/test_oradate.rb +76 -83
- data/test/test_oranumber.rb +405 -71
- data/test/test_rowid.rb +6 -11
- metadata +31 -32
- data/NEWS +0 -420
- data/ext/oci8/const.c +0 -165
- data/ext/oci8/define.c +0 -53
- data/ext/oci8/describe.c +0 -81
- data/ext/oci8/descriptor.c +0 -39
- data/ext/oci8/handle.c +0 -273
- data/ext/oci8/oranumber.c +0 -445
- data/ext/oci8/param.c +0 -37
- data/ext/oci8/server.c +0 -182
- data/ext/oci8/session.c +0 -99
- data/ext/oci8/svcctx.c +0 -238
- data/ruby-oci8.spec +0 -62
- data/support/README +0 -4
- data/support/runit/assert.rb +0 -281
- data/support/runit/cui/testrunner.rb +0 -101
- data/support/runit/error.rb +0 -4
- data/support/runit/method_mappable.rb +0 -20
- data/support/runit/robserver.rb +0 -25
- data/support/runit/setuppable.rb +0 -15
- data/support/runit/teardownable.rb +0 -16
- data/support/runit/testcase.rb +0 -113
- data/support/runit/testfailure.rb +0 -25
- data/support/runit/testresult.rb +0 -121
- data/support/runit/testsuite.rb +0 -43
- data/support/runit/version.rb +0 -3
- data/test/test_describe.rb +0 -137
data/lib/oci8/.document
ADDED
data/lib/oci8/compat.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
#
|
2
|
+
# add compatible code with old versions.
|
3
|
+
#
|
4
|
+
|
5
|
+
OCI_STMT_SELECT = :select_stmt
|
6
|
+
OCI_STMT_UPDATE = :update_stmt
|
7
|
+
OCI_STMT_DELETE = :delete_stmt
|
8
|
+
OCI_STMT_INSERT = :insert_stmt
|
9
|
+
OCI_STMT_CREATE = :create_stmt
|
10
|
+
OCI_STMT_DROP = :drop_stmt
|
11
|
+
OCI_STMT_ALTER = :alter_stmt
|
12
|
+
OCI_STMT_BEGIN = :begin_stmt
|
13
|
+
OCI_STMT_DECLARE = :declare_stmt
|
14
|
+
|
15
|
+
class OCI8
|
16
|
+
|
17
|
+
STMT_SELECT = :select_stmt
|
18
|
+
STMT_UPDATE = :update_stmt
|
19
|
+
STMT_DELETE = :delete_stmt
|
20
|
+
STMT_INSERT = :insert_stmt
|
21
|
+
STMT_CREATE = :create_stmt
|
22
|
+
STMT_DROP = :drop_stmt
|
23
|
+
STMT_ALTER = :alter_stmt
|
24
|
+
STMT_BEGIN = :begin_stmt
|
25
|
+
STMT_DECLARE = :declare_stmt
|
26
|
+
|
27
|
+
RAW = :raw
|
28
|
+
|
29
|
+
# varchar, varchar2
|
30
|
+
SQLT_CHR = :varchar2
|
31
|
+
# number, double precision, float, real, numeric, int, integer, smallint
|
32
|
+
SQLT_NUM = :number
|
33
|
+
# long
|
34
|
+
SQLT_LNG = :long
|
35
|
+
# date
|
36
|
+
SQLT_DAT = :date
|
37
|
+
# raw
|
38
|
+
SQLT_BIN = :raw
|
39
|
+
# long raw
|
40
|
+
SQLT_LBI = :long_raw
|
41
|
+
# char
|
42
|
+
SQLT_AFC = :char
|
43
|
+
# binary_float
|
44
|
+
SQLT_IBFLOAT = :binary_float
|
45
|
+
# binary_double
|
46
|
+
SQLT_IBDOUBLE = :binary_double
|
47
|
+
# rowid
|
48
|
+
SQLT_RDD = :rowid
|
49
|
+
# clob
|
50
|
+
SQLT_CLOB = :clob
|
51
|
+
# blob
|
52
|
+
SQLT_BLOB = :blob
|
53
|
+
# bfile
|
54
|
+
SQLT_BFILE = :bfile
|
55
|
+
# ref cursor
|
56
|
+
SQLT_RSET = 116
|
57
|
+
# timestamp
|
58
|
+
SQLT_TIMESTAMP = :timestamp
|
59
|
+
# timestamp with time zone
|
60
|
+
SQLT_TIMESTAMP_TZ = :timestamp_tz
|
61
|
+
# interval year to month
|
62
|
+
SQLT_INTERVAL_YM = :interval_ym
|
63
|
+
# interval day to second
|
64
|
+
SQLT_INTERVAL_DS = :interval_ds
|
65
|
+
# timestamp with local time zone
|
66
|
+
SQLT_TIMESTAMP_LTZ = :timestamp_ltz
|
67
|
+
|
68
|
+
# mapping of sql type number to sql type name.
|
69
|
+
SQLT_NAMES = {}
|
70
|
+
constants.each do |name|
|
71
|
+
next if name.to_s.index("SQLT_") != 0
|
72
|
+
val = const_get name.intern
|
73
|
+
if val.is_a? Fixnum
|
74
|
+
SQLT_NAMES[val] = name
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# add alias compatible with 'Oracle7 Module for Ruby'.
|
79
|
+
alias autocommit autocommit?
|
80
|
+
|
81
|
+
class Cursor
|
82
|
+
def self.select_number_as=(val)
|
83
|
+
if val == Fixnum
|
84
|
+
@@bind_unknown_number = OCI8::BindType::Fixnum
|
85
|
+
elsif val == Integer
|
86
|
+
@@bind_unknown_number = OCI8::BindType::Integer
|
87
|
+
elsif val == Float
|
88
|
+
@@bind_unknown_number = OCI8::BindType::Float
|
89
|
+
else
|
90
|
+
raise ArgumentError, "must be Fixnum, Integer or Float"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.select_number_as
|
95
|
+
case @@bind_unknown_number
|
96
|
+
when OCI8::BindType::Fixnum
|
97
|
+
return Fixnum
|
98
|
+
when OCI8::BindType::Integer
|
99
|
+
return Integer
|
100
|
+
when OCI8::BindType::Float
|
101
|
+
return Float
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# add alias compatible with 'Oracle7 Module for Ruby'.
|
106
|
+
alias getColNames get_col_names
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,489 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
class OCI8
|
4
|
+
|
5
|
+
module BindType
|
6
|
+
|
7
|
+
module Util # :nodoc:
|
8
|
+
|
9
|
+
@@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
|
+
|
13
|
+
@@default_timezone = :local
|
14
|
+
def self.default_timezone
|
15
|
+
@@default_timezone
|
16
|
+
end
|
17
|
+
|
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 session timezone.
|
24
|
+
def self.default_timezone=(tz)
|
25
|
+
if tz != :local and tz != :utc
|
26
|
+
raise ArgumentError, "expected :local or :utc but #{tz}"
|
27
|
+
end
|
28
|
+
@@default_timezone = tz
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def datetime_to_array(val, full)
|
34
|
+
# year
|
35
|
+
year = val.year
|
36
|
+
# month
|
37
|
+
if val.respond_to? :mon
|
38
|
+
month = val.mon
|
39
|
+
elsif val.respond_to? :month
|
40
|
+
month = val.month
|
41
|
+
else
|
42
|
+
raise "expect Time, Date or DateTime but #{val.class}"
|
43
|
+
end
|
44
|
+
# day
|
45
|
+
if val.respond_to? :mday
|
46
|
+
day = val.mday
|
47
|
+
elsif val.respond_to? :day
|
48
|
+
day = val.day
|
49
|
+
else
|
50
|
+
raise "expect Time, Date or DateTime but #{val.class}"
|
51
|
+
end
|
52
|
+
# hour
|
53
|
+
if val.respond_to? :hour
|
54
|
+
hour = val.hour
|
55
|
+
else
|
56
|
+
hour = 0
|
57
|
+
end
|
58
|
+
# minute
|
59
|
+
if val.respond_to? :min
|
60
|
+
minute = val.min
|
61
|
+
else
|
62
|
+
minute = 0
|
63
|
+
end
|
64
|
+
# second
|
65
|
+
if val.respond_to? :sec
|
66
|
+
sec = val.sec
|
67
|
+
else
|
68
|
+
sec = 0
|
69
|
+
end
|
70
|
+
return [year, month, day, hour, minute, sec] unless full
|
71
|
+
|
72
|
+
# sec_fraction
|
73
|
+
if val.respond_to? :sec_fraction
|
74
|
+
fsec = (val.sec_fraction * @@datetime_fsec_base).to_i
|
75
|
+
else
|
76
|
+
fsec = 0
|
77
|
+
end
|
78
|
+
# time zone
|
79
|
+
if val.respond_to? :offset
|
80
|
+
# DateTime
|
81
|
+
tz_min = (val.offset * 1440).to_i
|
82
|
+
elsif val.respond_to? :utc_offset
|
83
|
+
# Time
|
84
|
+
tz_min = val.utc_offset / 60
|
85
|
+
else
|
86
|
+
tz_hour = nil
|
87
|
+
tz_min = nil
|
88
|
+
end
|
89
|
+
if tz_min
|
90
|
+
if tz_min < 0
|
91
|
+
tz_min = - tz_min
|
92
|
+
tz_hour = - (tz_min / 60)
|
93
|
+
tz_min = (tz_min % 60)
|
94
|
+
else
|
95
|
+
tz_hour = tz_min / 60
|
96
|
+
tz_min = tz_min % 60
|
97
|
+
end
|
98
|
+
end
|
99
|
+
[year, month, day, hour, minute, sec, fsec, tz_hour, tz_min]
|
100
|
+
end
|
101
|
+
|
102
|
+
def ocidate_to_datetime(ary)
|
103
|
+
year, month, day, hour, minute, sec = ary
|
104
|
+
if @@default_timezone == :local
|
105
|
+
offset = @@datetime_offset
|
106
|
+
else
|
107
|
+
offset = 0
|
108
|
+
end
|
109
|
+
::DateTime.civil(year, month, day, hour, minute, sec, offset)
|
110
|
+
end
|
111
|
+
|
112
|
+
def ocidate_to_time(ary)
|
113
|
+
year, month, day, hour, minute, sec = ary
|
114
|
+
begin
|
115
|
+
::Time.send(@@default_timezone, year, month, day, hour, minute, sec)
|
116
|
+
rescue StandardError
|
117
|
+
ocidate_to_datetime(ary)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
if OCI8.oracle_client_version >= ORAVER_9_0
|
122
|
+
|
123
|
+
def ocitimestamp_to_datetime(ary)
|
124
|
+
year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
|
125
|
+
if sec >= 59 and fsec != 0
|
126
|
+
# convert to a DateTime via a String as a last resort.
|
127
|
+
if tz_hour >= 0 && tz_min >= 0
|
128
|
+
sign = ?+
|
129
|
+
else
|
130
|
+
sign = ?-
|
131
|
+
tz_hour = - tz_hour
|
132
|
+
tz_min = - tz_min
|
133
|
+
end
|
134
|
+
time_str = format("%04d-%02d-%02dT%02d:%02d:%02d.%09d%c%02d:%02d",
|
135
|
+
year, month, day, hour, minute, sec, fsec, sign, tz_hour, tz_min)
|
136
|
+
::DateTime.parse(time_str)
|
137
|
+
else
|
138
|
+
sec += fsec.to_r / 1000000000
|
139
|
+
offset = tz_hour.to_r / 24 + tz_min.to_r / 1440
|
140
|
+
::DateTime.civil(year, month, day, hour, minute, sec, offset)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def ocitimestamp_to_time(ary)
|
145
|
+
year, month, day, hour, minute, sec, fsec, tz_hour, tz_min = ary
|
146
|
+
|
147
|
+
if tz_hour == 0 and tz_min == 0
|
148
|
+
timezone = :utc
|
149
|
+
elsif @@time_offset == tz_hour * 3600 + tz_min * 60
|
150
|
+
timezone = :local
|
151
|
+
end
|
152
|
+
if timezone
|
153
|
+
begin
|
154
|
+
# Ruby 1.9 Time class's resolution is nanosecond.
|
155
|
+
# But the last argument type is millisecond.
|
156
|
+
# 'fsec' is converted to a Float to pass sub-millisecond part.
|
157
|
+
return ::Time.send(timezone, year, month, day, hour, minute, sec, fsec / 1000.0)
|
158
|
+
rescue StandardError
|
159
|
+
end
|
160
|
+
end
|
161
|
+
ocitimestamp_to_datetime(ary)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class DateTimeViaOCIDate < OCI8::BindType::OCIDate
|
167
|
+
include OCI8::BindType::Util
|
168
|
+
|
169
|
+
def set(val) # :nodoc:
|
170
|
+
val &&= datetime_to_array(val, false)
|
171
|
+
super(val)
|
172
|
+
end
|
173
|
+
|
174
|
+
def get() # :nodoc:
|
175
|
+
val = super()
|
176
|
+
val ? ocidate_to_datetime(val) : nil
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
class TimeViaOCIDate < OCI8::BindType::OCIDate
|
181
|
+
include OCI8::BindType::Util
|
182
|
+
|
183
|
+
def set(val) # :nodoc:
|
184
|
+
val &&= datetime_to_array(val, false)
|
185
|
+
super(val)
|
186
|
+
end
|
187
|
+
|
188
|
+
def get() # :nodoc:
|
189
|
+
val = super()
|
190
|
+
val ? ocidate_to_time(val) : nil
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
if OCI8.oracle_client_version >= ORAVER_9_0
|
195
|
+
class DateTimeViaOCITimestamp < OCI8::BindType::OCITimestamp
|
196
|
+
include OCI8::BindType::Util
|
197
|
+
|
198
|
+
def set(val) # :nodoc:
|
199
|
+
val &&= datetime_to_array(val, true)
|
200
|
+
super(val)
|
201
|
+
end
|
202
|
+
|
203
|
+
def get() # :nodoc:
|
204
|
+
val = super()
|
205
|
+
val ? ocitimestamp_to_datetime(val) : nil
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class TimeViaOCITimestamp < OCI8::BindType::OCITimestamp
|
210
|
+
include OCI8::BindType::Util
|
211
|
+
|
212
|
+
def set(val) # :nodoc:
|
213
|
+
val &&= datetime_to_array(val, true)
|
214
|
+
super(val)
|
215
|
+
end
|
216
|
+
|
217
|
+
def get() # :nodoc:
|
218
|
+
val = super()
|
219
|
+
val ? ocitimestamp_to_time(val) : nil
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
#--
|
226
|
+
# OCI8::BindType::DateTime
|
227
|
+
#++
|
228
|
+
# This is a helper class to bind ruby's
|
229
|
+
# DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]
|
230
|
+
# object as Oracle's <tt>TIMESTAMP WITH TIME ZONE</tt> datatype.
|
231
|
+
#
|
232
|
+
# == Select
|
233
|
+
#
|
234
|
+
# The fetched value for a <tt>DATE</tt>, <tt>TIMESTAMP</tt>, <tt>TIMESTAMP WITH
|
235
|
+
# TIME ZONE</tt> or <tt>TIMESTAMP WITH LOCAL TIME ZONE</tt> column
|
236
|
+
# is a DateTime[http://www.ruby-doc.org/core/classes/DateTime.html].
|
237
|
+
# The time zone part is a session time zone if the Oracle datatype doesn't
|
238
|
+
# have time zone information. The session time zone is the client machine's
|
239
|
+
# time zone by default.
|
240
|
+
#
|
241
|
+
# You can change the session time zone by executing the following SQL.
|
242
|
+
#
|
243
|
+
# ALTER SESSION SET TIME_ZONE='-05:00'
|
244
|
+
#
|
245
|
+
# == Bind
|
246
|
+
#
|
247
|
+
# To bind a DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]
|
248
|
+
# value implicitly:
|
249
|
+
#
|
250
|
+
# conn.exec("INSERT INTO lunar_landings(ship_name, landing_time) VALUES(:1, :2)",
|
251
|
+
# 'Apollo 11',
|
252
|
+
# DateTime.parse('1969-7-20 20:17:40 00:00'))
|
253
|
+
#
|
254
|
+
# The bind variable <code>:2</code> is bound as <tt>TIMESTAMP WITH TIME ZONE</tt> on Oracle.
|
255
|
+
#
|
256
|
+
# To bind explicitly:
|
257
|
+
#
|
258
|
+
# cursor = conn.exec("INSERT INTO lunar_landings(ship_name, landing_time) VALUES(:1, :2)")
|
259
|
+
# cursor.bind_param(':1', nil, String, 60)
|
260
|
+
# cursor.bind_param(':2', nil, DateTime)
|
261
|
+
# [['Apollo 11', DateTime.parse('1969-07-20 20:17:40 00:00'))],
|
262
|
+
# ['Apollo 12', DateTime.parse('1969-11-19 06:54:35 00:00'))],
|
263
|
+
# ['Apollo 14', DateTime.parse('1971-02-05 09:18:11 00:00'))],
|
264
|
+
# ['Apollo 15', DateTime.parse('1971-07-30 22:16:29 00:00'))],
|
265
|
+
# ['Apollo 16', DateTime.parse('1972-04-21 02:23:35 00:00'))],
|
266
|
+
# ['Apollo 17', DateTime.parse('1972-12-11 19:54:57 00:00'))]
|
267
|
+
# ].each do |ship_name, landing_time|
|
268
|
+
# cursor[':1'] = ship_name
|
269
|
+
# cursor[':2'] = landing_time
|
270
|
+
# cursor.exec
|
271
|
+
# end
|
272
|
+
# cursor.close
|
273
|
+
#
|
274
|
+
# On setting a object to the bind variable, you can use any object
|
275
|
+
# which has at least three instance methods _year_, _mon_ (or _month_)
|
276
|
+
# and _mday_ (or _day_). If the object responses to _hour_, _min_,
|
277
|
+
# _sec_ or _sec_fraction_, the responsed values are used for hour,
|
278
|
+
# minute, second or fraction of a second respectively.
|
279
|
+
# If not, zeros are set. If the object responses to _offset_ or
|
280
|
+
# _utc_offset_, it is used for time zone. If not, the session time
|
281
|
+
# zone is used.
|
282
|
+
#
|
283
|
+
# The acceptable value are listed below.
|
284
|
+
# _year_:: -4712 to 9999 [excluding year 0]
|
285
|
+
# _mon_ (or _month_):: 0 to 12
|
286
|
+
# _mday_ (or _day_):: 0 to 31 [depends on the month]
|
287
|
+
# _hour_:: 0 to 23
|
288
|
+
# _min_:: 0 to 59
|
289
|
+
# _sec_:: 0 to 59
|
290
|
+
# _sec_fraction_:: 0 to (999_999_999.to_r / (24*60*60* 1_000_000_000)) [999,999,999 nanoseconds]
|
291
|
+
# _offset_:: (-12.to_r / 24) to (14.to_r / 24) [-12:00 to +14:00]
|
292
|
+
# _utc_offset_:: -12*3600 <= utc_offset <= 24*3600 [-12:00 to +14:00]
|
293
|
+
#
|
294
|
+
# The output value of the bind varible is always a
|
295
|
+
# DateTime[http://www.ruby-doc.org/core/classes/DateTime.html].
|
296
|
+
#
|
297
|
+
# cursor = conn.exec("BEGIN :ts := current_timestamp; END")
|
298
|
+
# cursor.bind_param(:ts, nil, DateTime)
|
299
|
+
# cursor.exec
|
300
|
+
# cursor[:ts] # => a DateTime.
|
301
|
+
# cursor.close
|
302
|
+
#
|
303
|
+
class DateTime
|
304
|
+
if OCI8.oracle_client_version >= ORAVER_9_0
|
305
|
+
def self.create(con, val, param, max_array_size)
|
306
|
+
if true # TODO: check Oracle server version
|
307
|
+
DateTimeViaOCITimestamp.new(con, val, param, max_array_size)
|
308
|
+
else
|
309
|
+
DateTimeViaOCIDate.new(con, val, param, max_array_size)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
else
|
313
|
+
def self.create(con, val, param, max_array_size)
|
314
|
+
DateTimeViaOCIDate.new(con, val, param, max_array_size)
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
class Time
|
320
|
+
if OCI8.oracle_client_version >= ORAVER_9_0
|
321
|
+
def self.create(con, val, param, max_array_size)
|
322
|
+
if true # TODO: check Oracle server version
|
323
|
+
TimeViaOCITimestamp.new(con, val, param, max_array_size)
|
324
|
+
else
|
325
|
+
TimeViaOCIDate.new(con, val, param, max_array_size)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
else
|
329
|
+
def self.create(con, val, param, max_array_size)
|
330
|
+
TimeViaOCIDate.new(con, val, param, max_array_size)
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
if OCI8.oracle_client_version >= ORAVER_9_0
|
336
|
+
#--
|
337
|
+
# OCI8::BindType::IntervalYM
|
338
|
+
#++
|
339
|
+
#
|
340
|
+
# This is a helper class to bind ruby's
|
341
|
+
# Integer[http://www.ruby-doc.org/core/classes/Integer.html]
|
342
|
+
# object as Oracle's <tt>INTERVAL YEAR TO MONTH</tt> datatype.
|
343
|
+
#
|
344
|
+
# == Select
|
345
|
+
#
|
346
|
+
# The fetched value for a <tt>INTERVAL YEAR TO MONTH</tt> column
|
347
|
+
# is an Integer[http://www.ruby-doc.org/core/classes/Integer.html]
|
348
|
+
# which means the months between two timestamps.
|
349
|
+
#
|
350
|
+
# == Bind
|
351
|
+
#
|
352
|
+
# You cannot bind as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
|
353
|
+
# It must be bound explicitly with :interval_ym.
|
354
|
+
#
|
355
|
+
# # output bind variable
|
356
|
+
# cursor = conn.parse(<<-EOS)
|
357
|
+
# BEGIN
|
358
|
+
# :interval := (:ts1 - :ts2) YEAR TO MONTH;
|
359
|
+
# END;
|
360
|
+
# EOS
|
361
|
+
# cursor.bind_param(:interval, nil, :interval_ym)
|
362
|
+
# cursor.bind_param(:ts1, DateTime.parse('1969-11-19 06:54:35 00:00'))
|
363
|
+
# cursor.bind_param(:ts2, DateTime.parse('1969-07-20 20:17:40 00:00'))
|
364
|
+
# cursor.exec
|
365
|
+
# cursor[:interval] # => 4 (months)
|
366
|
+
# cursor.close
|
367
|
+
#
|
368
|
+
# # input bind variable
|
369
|
+
# cursor = conn.parse(<<-EOS)
|
370
|
+
# BEGIN
|
371
|
+
# :ts1 := :ts2 + :interval;
|
372
|
+
# END;
|
373
|
+
# EOS
|
374
|
+
# cursor.bind_param(:ts1, nil, DateTime)
|
375
|
+
# cursor.bind_param(:ts2, Date.parse('1969-11-19'))
|
376
|
+
# cursor.bind_param(:interval, 4, :interval_ym)
|
377
|
+
# cursor.exec
|
378
|
+
# cursor[:ts1].strftime('%Y-%m-%d') # => 1970-03-19
|
379
|
+
# cursor.close
|
380
|
+
#
|
381
|
+
class IntervalYM < OCI8::BindType::OCIIntervalYM
|
382
|
+
def set(val) # :nodoc:
|
383
|
+
unless val.nil?
|
384
|
+
val = [val / 12, val % 12]
|
385
|
+
end
|
386
|
+
super(val)
|
387
|
+
end
|
388
|
+
def get() # :nodoc:
|
389
|
+
val = super()
|
390
|
+
return nil if val.nil?
|
391
|
+
year, month = val
|
392
|
+
year * 12 + month
|
393
|
+
end
|
394
|
+
end # OCI8::BindType::IntervalYM
|
395
|
+
|
396
|
+
#--
|
397
|
+
# OCI8::BindType::IntervalDS
|
398
|
+
#++
|
399
|
+
#
|
400
|
+
# This is a helper class to bind ruby's
|
401
|
+
# Rational[http://www.ruby-doc.org/core/classes/Rational.html]
|
402
|
+
# object as Oracle's <tt>INTERVAL DAY TO SECOND</tt> datatype.
|
403
|
+
#
|
404
|
+
# == Select
|
405
|
+
#
|
406
|
+
# The fetched value for a <tt>INTERVAL DAY TO SECOND</tt> column
|
407
|
+
# is a Rational[http://www.ruby-doc.org/core/classes/Rational.html]
|
408
|
+
# or an Integer[http://www.ruby-doc.org/core/classes/Integer.html].
|
409
|
+
# The value is usable to apply to
|
410
|
+
# DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#+ and
|
411
|
+
# DateTime[http://www.ruby-doc.org/core/classes/DateTime.html]#-.
|
412
|
+
#
|
413
|
+
# == Bind
|
414
|
+
#
|
415
|
+
# You cannot bind as <tt>INTERVAL YEAR TO MONTH</tt> implicitly.
|
416
|
+
# It must be bound explicitly with :interval_ds.
|
417
|
+
#
|
418
|
+
# # output
|
419
|
+
# ts1 = DateTime.parse('1969-11-19 06:54:35 00:00')
|
420
|
+
# ts2 = DateTime.parse('1969-07-20 20:17:40 00:00')
|
421
|
+
# cursor = conn.parse(<<-EOS)
|
422
|
+
# BEGIN
|
423
|
+
# :itv := (:ts1 - :ts2) DAY TO SECOND;
|
424
|
+
# END;
|
425
|
+
# EOS
|
426
|
+
# cursor.bind_param(:itv, nil, :interval_ds)
|
427
|
+
# cursor.bind_param(:ts1, ts1)
|
428
|
+
# cursor.bind_param(:ts2, ts2)
|
429
|
+
# cursor.exec
|
430
|
+
# cursor[:itv] # == ts1 - ts2
|
431
|
+
# cursor.close
|
432
|
+
#
|
433
|
+
# # input
|
434
|
+
# ts2 = DateTime.parse('1969-07-20 20:17:40 00:00')
|
435
|
+
# itv = 121 + 10.to_r/24 + 36.to_r/(24*60) + 55.to_r/(24*60*60)
|
436
|
+
# # 121 days, 10 hours, 36 minutes, 55 seconds
|
437
|
+
# cursor = conn.parse(<<-EOS)
|
438
|
+
# BEGIN
|
439
|
+
# :ts1 := :ts2 + :itv;
|
440
|
+
# END;
|
441
|
+
# EOS
|
442
|
+
# cursor.bind_param(:ts1, nil, DateTime)
|
443
|
+
# cursor.bind_param(:ts2, ts2)
|
444
|
+
# cursor.bind_param(:itv, itv, :interval_ds)
|
445
|
+
# cursor.exec
|
446
|
+
# cursor[:ts1].strftime('%Y-%m-%d %H:%M:%S') # => 1969-11-19 06:54:35
|
447
|
+
# cursor.close
|
448
|
+
#
|
449
|
+
class IntervalDS < OCI8::BindType::OCIIntervalDS
|
450
|
+
@@hour = 1 / 24.to_r
|
451
|
+
@@minute = @@hour / 60
|
452
|
+
@@sec = @@minute / 60
|
453
|
+
@@fsec = @@sec / 1000000000
|
454
|
+
|
455
|
+
def set(val) # :nodoc:
|
456
|
+
unless val.nil?
|
457
|
+
if val < 0
|
458
|
+
is_minus = true
|
459
|
+
val = -val
|
460
|
+
else
|
461
|
+
is_minus = false
|
462
|
+
end
|
463
|
+
day, val = val.divmod 1
|
464
|
+
hour, val = (val * 24).divmod 1
|
465
|
+
minute, val = (val * 60).divmod 1
|
466
|
+
sec, val = (val * 60).divmod 1
|
467
|
+
fsec, val = (val * 1000000000).divmod 1
|
468
|
+
if is_minus
|
469
|
+
day = - day
|
470
|
+
hour = - hour
|
471
|
+
minute = - minute
|
472
|
+
sec = - sec
|
473
|
+
fsec = - fsec
|
474
|
+
end
|
475
|
+
val = [day, hour, minute, sec, fsec]
|
476
|
+
end
|
477
|
+
super(val)
|
478
|
+
end
|
479
|
+
|
480
|
+
def get() # :nodoc:
|
481
|
+
val = super()
|
482
|
+
return nil if val.nil?
|
483
|
+
day, hour, minute, sec, fsec = val
|
484
|
+
day + (hour * @@hour) + (minute * @@minute) + (sec * @@sec) + (fsec * @@fsec)
|
485
|
+
end
|
486
|
+
end # OCI8::BindType::IntervalDS
|
487
|
+
end
|
488
|
+
end # OCI8::BindType
|
489
|
+
end # OCI8
|