ruby-oci8-master 2.0.7

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.
Files changed (84) hide show
  1. data/ChangeLog +2321 -0
  2. data/Makefile +88 -0
  3. data/NEWS +303 -0
  4. data/README +76 -0
  5. data/VERSION +1 -0
  6. data/dist-files +83 -0
  7. data/doc/api.en.html +527 -0
  8. data/doc/api.en.rd +554 -0
  9. data/doc/api.ja.html +525 -0
  10. data/doc/api.ja.rd +557 -0
  11. data/doc/manual.css +35 -0
  12. data/ext/oci8/.document +18 -0
  13. data/ext/oci8/MANIFEST +18 -0
  14. data/ext/oci8/apiwrap.c.tmpl +182 -0
  15. data/ext/oci8/apiwrap.h.tmpl +61 -0
  16. data/ext/oci8/apiwrap.rb +91 -0
  17. data/ext/oci8/apiwrap.yml +1455 -0
  18. data/ext/oci8/attr.c +105 -0
  19. data/ext/oci8/bind.c +366 -0
  20. data/ext/oci8/connection_pool.c +199 -0
  21. data/ext/oci8/encoding.c +289 -0
  22. data/ext/oci8/env.c +178 -0
  23. data/ext/oci8/error.c +378 -0
  24. data/ext/oci8/extconf.rb +179 -0
  25. data/ext/oci8/lob.c +805 -0
  26. data/ext/oci8/metadata.c +232 -0
  27. data/ext/oci8/object.c +727 -0
  28. data/ext/oci8/oci8.c +1156 -0
  29. data/ext/oci8/oci8.h +574 -0
  30. data/ext/oci8/oci8lib.c +527 -0
  31. data/ext/oci8/ocidatetime.c +484 -0
  32. data/ext/oci8/ocihandle.c +751 -0
  33. data/ext/oci8/ocinumber.c +1612 -0
  34. data/ext/oci8/oraconf.rb +1119 -0
  35. data/ext/oci8/oradate.c +611 -0
  36. data/ext/oci8/oranumber_util.c +352 -0
  37. data/ext/oci8/oranumber_util.h +24 -0
  38. data/ext/oci8/post-config.rb +5 -0
  39. data/ext/oci8/stmt.c +673 -0
  40. data/ext/oci8/thread_util.c +85 -0
  41. data/ext/oci8/thread_util.h +30 -0
  42. data/ext/oci8/win32.c +137 -0
  43. data/lib/.document +1 -0
  44. data/lib/dbd/OCI8.rb +591 -0
  45. data/lib/oci8.rb.in +94 -0
  46. data/lib/oci8/.document +8 -0
  47. data/lib/oci8/bindtype.rb +349 -0
  48. data/lib/oci8/compat.rb +113 -0
  49. data/lib/oci8/connection_pool.rb +99 -0
  50. data/lib/oci8/datetime.rb +611 -0
  51. data/lib/oci8/encoding-init.rb +74 -0
  52. data/lib/oci8/encoding.yml +537 -0
  53. data/lib/oci8/metadata.rb +2132 -0
  54. data/lib/oci8/object.rb +581 -0
  55. data/lib/oci8/oci8.rb +721 -0
  56. data/lib/oci8/ocihandle.rb +425 -0
  57. data/lib/oci8/oracle_version.rb +144 -0
  58. data/lib/oci8/properties.rb +73 -0
  59. data/metaconfig +142 -0
  60. data/pre-distclean.rb +7 -0
  61. data/ruby-oci8.gemspec +63 -0
  62. data/setup.rb +1331 -0
  63. data/test/README +4 -0
  64. data/test/config.rb +122 -0
  65. data/test/test_all.rb +51 -0
  66. data/test/test_appinfo.rb +63 -0
  67. data/test/test_array_dml.rb +333 -0
  68. data/test/test_bind_raw.rb +46 -0
  69. data/test/test_bind_time.rb +178 -0
  70. data/test/test_break.rb +96 -0
  71. data/test/test_clob.rb +82 -0
  72. data/test/test_connstr.rb +81 -0
  73. data/test/test_datetime.rb +582 -0
  74. data/test/test_dbi.rb +366 -0
  75. data/test/test_dbi_clob.rb +53 -0
  76. data/test/test_encoding.rb +100 -0
  77. data/test/test_error.rb +88 -0
  78. data/test/test_metadata.rb +1399 -0
  79. data/test/test_oci8.rb +434 -0
  80. data/test/test_oracle_version.rb +70 -0
  81. data/test/test_oradate.rb +256 -0
  82. data/test/test_oranumber.rb +746 -0
  83. data/test/test_rowid.rb +33 -0
  84. metadata +137 -0
@@ -0,0 +1,582 @@
1
+ require 'oci8'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/config'
4
+ require 'scanf'
5
+
6
+ class TestDateTime < Test::Unit::TestCase
7
+
8
+ def timezone_string(tzh, tzm)
9
+ if tzh >= 0
10
+ format("+%02d:%02d", tzh, tzm)
11
+ else
12
+ format("-%02d:%02d", -tzh, -tzm)
13
+ end
14
+ end
15
+
16
+ def string_to_time(str)
17
+ /(\d+)-(\d+)-(\d+) ?(?:(\d+):(\d+):(\d+))?(?:\.(\d+))? ?([+-]\d+:\d+)?/ =~ str
18
+ args = []
19
+ args << $1.to_i # year
20
+ args << $2.to_i # month
21
+ args << $3.to_i # day
22
+ args << $4.to_i if $4 # hour
23
+ args << $5.to_i if $5 # minute
24
+ if $8
25
+ args << $6.to_i + $7.to_i.to_r / ('1' + '0' * ($7.length)).to_i
26
+ args << $8
27
+ Time.new(*args)
28
+ else
29
+ if $6
30
+ args << $6.to_i
31
+ end
32
+ if $7
33
+ args << $7.to_i.to_r * 1000000 / ('1' + '0' * ($7.length)).to_i
34
+ end
35
+ # no time zone
36
+ Time.local(*args)
37
+ end
38
+ #Time.local(*str.split(/[- :\.]/).collect do |n| n.to_i; end)
39
+ end
40
+
41
+ def setup
42
+ @conn = get_oci8_connection
43
+ @local_timezone = timezone_string(*((::Time.now.utc_offset / 60).divmod 60))
44
+ end
45
+
46
+ def teardown
47
+ @conn.logoff
48
+ end
49
+
50
+ def test_date_select
51
+ ['2005-12-31 23:59:59',
52
+ '2006-01-01 00:00:00'].each do |date|
53
+ @conn.exec(<<-EOS) do |row|
54
+ SELECT TO_DATE('#{date}', 'YYYY-MM-DD HH24:MI:SS') FROM dual
55
+ EOS
56
+ assert_equal(Time.local(*date.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
57
+ end
58
+ end
59
+ end
60
+
61
+ def test_date_out_bind
62
+ cursor = @conn.parse(<<-EOS)
63
+ BEGIN
64
+ :out := TO_DATE(:in, 'YYYY-MM-DD HH24:MI:SS');
65
+ END;
66
+ EOS
67
+ cursor.bind_param(:out, nil, DateTime)
68
+ cursor.bind_param(:in, nil, String, 36)
69
+ ['2005-12-31 23:59:59',
70
+ '2006-01-01 00:00:00'].each do |date|
71
+ cursor[:in] = date
72
+ cursor.exec
73
+ assert_equal(DateTime.parse(date + @local_timezone), cursor[:out])
74
+ end
75
+ cursor.close
76
+ end
77
+
78
+ def test_date_in_bind
79
+ cursor = @conn.parse(<<-EOS)
80
+ DECLARE
81
+ dt date;
82
+ BEGIN
83
+ dt := :in;
84
+ :out := TO_CHAR(dt, 'YYYY-MM-DD HH24:MI:SS');
85
+ END;
86
+ EOS
87
+ cursor.bind_param(:out, nil, String, 33)
88
+ cursor.bind_param(:in, nil, DateTime)
89
+ ['2005-12-31 23:59:59',
90
+ '2006-01-01 00:00:00'].each do |date|
91
+ cursor[:in] = DateTime.parse(date + @local_timezone)
92
+ cursor.exec
93
+ assert_equal(date, cursor[:out])
94
+ end
95
+ cursor.close
96
+ end
97
+
98
+ def test_timestamp_select
99
+ ['2005-12-31 23:59:59.999999000',
100
+ '2006-01-01 00:00:00.000000000'].each do |date|
101
+ @conn.exec(<<-EOS) do |row|
102
+ SELECT TO_TIMESTAMP('#{date}', 'YYYY-MM-DD HH24:MI:SS.FF') FROM dual
103
+ EOS
104
+ assert_equal(Time.local(*date.scanf("%d-%d-%d %d:%d:%d.%06d")), row[0])
105
+ end
106
+ end
107
+ end
108
+
109
+ def test_timestamp_out_bind
110
+ cursor = @conn.parse(<<-EOS)
111
+ BEGIN
112
+ :out := TO_TIMESTAMP(:in, 'YYYY-MM-DD HH24:MI:SS.FF');
113
+ END;
114
+ EOS
115
+ cursor.bind_param(:out, nil, DateTime)
116
+ cursor.bind_param(:in, nil, String, 36)
117
+ ['2005-12-31 23:59:59.999999000',
118
+ '2006-01-01 00:00:00.000000000'].each do |date|
119
+ cursor[:in] = date
120
+ cursor.exec
121
+ assert_equal(DateTime.parse(date + @local_timezone), cursor[:out])
122
+ end
123
+ cursor.close
124
+ end
125
+
126
+ def test_timestamp_in_bind
127
+ cursor = @conn.parse(<<-EOS)
128
+ BEGIN
129
+ :out := TO_CHAR(:in, 'YYYY-MM-DD HH24:MI:SS.FF');
130
+ END;
131
+ EOS
132
+ cursor.bind_param(:out, nil, String, 33)
133
+ cursor.bind_param(:in, nil, DateTime)
134
+ ['2005-12-31 23:59:59.999999000',
135
+ '2006-01-01 00:00:00.000000000'].each do |date|
136
+ cursor[:in] = DateTime.parse(date + @local_timezone)
137
+ cursor.exec
138
+ assert_equal(date, cursor[:out])
139
+ end
140
+ cursor.close
141
+ end
142
+
143
+ def test_timestamp_tz_select
144
+ ['2005-12-31 23:59:59.999999000 +08:30',
145
+ '2006-01-01 00:00:00.000000000 -08:30'].each do |date|
146
+ @conn.exec(<<-EOS) do |row|
147
+ SELECT TO_TIMESTAMP_TZ('#{date}', 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM') FROM dual
148
+ EOS
149
+ expected_val = begin
150
+ string_to_time(date)
151
+ rescue
152
+ DateTime.parse(date)
153
+ end
154
+ assert_equal(expected_val, row[0])
155
+ end
156
+ end
157
+ end
158
+
159
+ def test_timestamp_tz_out_bind
160
+ cursor = @conn.parse(<<-EOS)
161
+ BEGIN
162
+ :out := TO_TIMESTAMP_TZ(:in, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM');
163
+ END;
164
+ EOS
165
+ cursor.bind_param(:out, nil, DateTime)
166
+ cursor.bind_param(:in, nil, String, 36)
167
+ ['2005-12-31 23:59:59.999999000 +08:30',
168
+ '2006-01-01 00:00:00.000000000 -08:30'].each do |date|
169
+ cursor[:in] = date
170
+ cursor.exec
171
+ assert_equal(DateTime.parse(date), cursor[:out])
172
+ end
173
+ cursor.close
174
+ end
175
+
176
+ def test_timestamp_tz_in_bind
177
+ cursor = @conn.parse(<<-EOS)
178
+ BEGIN
179
+ :out := TO_CHAR(:in, 'YYYY-MM-DD HH24:MI:SS.FF TZH:TZM');
180
+ END;
181
+ EOS
182
+ cursor.bind_param(:out, nil, String, 36)
183
+ cursor.bind_param(:in, nil, DateTime)
184
+ ['2005-12-31 23:59:59.999999000 +08:30',
185
+ '2006-01-01 00:00:00.000000000 -08:30'].each do |date|
186
+ cursor[:in] = DateTime.parse(date)
187
+ cursor.exec
188
+ assert_equal(date, cursor[:out])
189
+ end
190
+ cursor.close
191
+ end
192
+
193
+ def test_datetype_duck_typing
194
+ cursor = @conn.parse("BEGIN :out := :in; END;")
195
+ cursor.bind_param(:in, nil, DateTime)
196
+ cursor.bind_param(:out, nil, DateTime)
197
+ obj = Object.new
198
+ # test year, month, day
199
+ def obj.year; 2006; end
200
+ def obj.month; 12; end
201
+ def obj.day; 31; end
202
+ cursor[:in] = obj
203
+ cursor.exec
204
+ assert_equal(DateTime.parse('2006-12-31 00:00:00' + @local_timezone), cursor[:out])
205
+ # test hour
206
+ def obj.hour; 23; end
207
+ cursor[:in] = obj
208
+ cursor.exec
209
+ assert_equal(DateTime.parse('2006-12-31 23:00:00' + @local_timezone), cursor[:out])
210
+ # test min
211
+ def obj.min; 59; end
212
+ cursor[:in] = obj
213
+ cursor.exec
214
+ assert_equal(DateTime.parse('2006-12-31 23:59:00' + @local_timezone), cursor[:out])
215
+ # test sec
216
+ def obj.sec; 59; end
217
+ cursor[:in] = obj
218
+ cursor.exec
219
+ assert_equal(DateTime.parse('2006-12-31 23:59:59' + @local_timezone), cursor[:out])
220
+
221
+ # test sec_fraction
222
+ def obj.sec_fraction; DateTime.parse('0001-01-01 00:00:00.000001').sec_fraction * 999999 ; end
223
+ cursor[:in] = obj
224
+ cursor.exec
225
+ assert_equal(DateTime.parse('2006-12-31 23:59:59.999999' + @local_timezone), cursor[:out])
226
+ # test utc_offset (Time)
227
+ def obj.utc_offset; @utc_offset; end
228
+ obj.instance_variable_set(:@utc_offset, 9 * 60 * 60)
229
+ cursor[:in] = obj
230
+ cursor.exec
231
+ assert_equal(DateTime.parse('2006-12-31 23:59:59.999999 +09:00'), cursor[:out])
232
+ obj.instance_variable_set(:@utc_offset, -5 * 60 * 60)
233
+ cursor[:in] = obj
234
+ cursor.exec
235
+ assert_equal(DateTime.parse('2006-12-31 23:59:59.999999 -05:00'), cursor[:out])
236
+ # test offset (DateTime)
237
+ def obj.offset; @offset; end
238
+ obj.instance_variable_set(:@offset, 9.to_r / 24)
239
+ cursor[:in] = obj
240
+ cursor.exec
241
+ assert_equal(DateTime.parse('2006-12-31 23:59:59.999999 +09:00'), cursor[:out])
242
+ obj.instance_variable_set(:@offset, -5.to_r / 24)
243
+ cursor[:in] = obj
244
+ cursor.exec
245
+ assert_equal(DateTime.parse('2006-12-31 23:59:59.999999 -05:00'), cursor[:out])
246
+ end
247
+
248
+ def test_timezone
249
+ begin
250
+ # temporarily change the mapping to test OCI8::BindType::Util.default_timezone.
251
+ assert_raise(ArgumentError) do
252
+ OCI8::BindType::Util.default_timezone = :invalid_value
253
+ end
254
+
255
+ =begin
256
+ [:local, :utc].each do |tz|
257
+ OCI8::BindType::Util.default_timezone = tz
258
+ @conn.exec("select sysdate, to_date('2008-01-02', 'yyyy-mm-dd') from dual") do |row|
259
+ row.each do |dt|
260
+ assert_kind_of(Time, dt)
261
+ assert_equal(tz, dt.utc? ? :utc : :local)
262
+ end
263
+ assert_equal(2008, row[1].year)
264
+ assert_equal(1, row[1].month)
265
+ assert_equal(2, row[1].day)
266
+ end
267
+ end
268
+ =end
269
+ ensure
270
+ OCI8::BindType::Util.default_timezone = :local
271
+ end
272
+
273
+ ses_tz = nil
274
+ @conn.exec('select sessiontimezone from dual') do |row|
275
+ ses_tz = row[0]
276
+ end
277
+
278
+ begin
279
+ ['+09:00', '+00:00', '-05:00'].each do |tz|
280
+ @conn.exec("alter session set time_zone = '#{tz}'")
281
+ @conn.exec("select current_timestamp, sysdate, to_timestamp('2008-01-02', 'yyyy-mm-dd') from dual") do |row|
282
+ row.each do |dt|
283
+ case dt
284
+ when Time
285
+ assert_equal(tz, timezone_string(*((dt.utc_offset / 60).divmod 60)))
286
+ when DateTime
287
+ tz = tz.gsub(/:/, '') if RUBY_VERSION <= '1.8.5'
288
+ assert_equal(tz, dt.zone)
289
+ else
290
+ flunk "unexpedted type #{dt.class}"
291
+ end
292
+ end
293
+ assert_equal(2008, row[2].year)
294
+ assert_equal(1, row[2].month)
295
+ assert_equal(2, row[2].day)
296
+ end
297
+ end
298
+ ensure
299
+ @conn.exec("alter session set time_zone = '#{ses_tz}'")
300
+ end
301
+ end
302
+
303
+ def test_interval_ym_select
304
+ [['2006-01-01', '2004-03-01'],
305
+ ['2006-01-01', '2005-03-01'],
306
+ ['2006-01-01', '2006-03-01'],
307
+ ['2006-01-01', '2007-03-01']
308
+ ].each do |date1, date2|
309
+ @conn.exec(<<-EOS) do |row|
310
+ SELECT (TO_TIMESTAMP('#{date1}', 'YYYY-MM-DD')
311
+ - TO_TIMESTAMP('#{date2}', 'YYYY-MM-DD')) YEAR TO MONTH
312
+ FROM dual
313
+ EOS
314
+ assert_equal(DateTime.parse(date1), DateTime.parse(date2) >> row[0])
315
+ end
316
+ end
317
+ end
318
+
319
+ def test_interval_ym_out_bind
320
+ cursor = @conn.parse(<<-EOS)
321
+ DECLARE
322
+ ts1 TIMESTAMP;
323
+ ts2 TIMESTAMP;
324
+ BEGIN
325
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD');
326
+ ts2 := TO_TIMESTAMP(:in2, 'YYYY-MM-DD');
327
+ :out := (ts1 - ts2) YEAR TO MONTH;
328
+ END;
329
+ EOS
330
+ cursor.bind_param(:out, nil, :interval_ym)
331
+ cursor.bind_param(:in1, nil, String, 36)
332
+ cursor.bind_param(:in2, nil, String, 36)
333
+ [['2006-01-01', '2004-03-01'],
334
+ ['2006-01-01', '2005-03-01'],
335
+ ['2006-01-01', '2006-03-01'],
336
+ ['2006-01-01', '2007-03-01']
337
+ ].each do |date1, date2|
338
+ cursor[:in1] = date1
339
+ cursor[:in2] = date2
340
+ cursor.exec
341
+ assert_equal(DateTime.parse(date1), DateTime.parse(date2) >> cursor[:out])
342
+ end
343
+ cursor.close
344
+ end
345
+
346
+ def test_interval_ym_in_bind
347
+ cursor = @conn.parse(<<-EOS)
348
+ DECLARE
349
+ ts1 TIMESTAMP;
350
+ BEGIN
351
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD');
352
+ :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD');
353
+ END;
354
+ EOS
355
+ cursor.bind_param(:out, nil, String, 36)
356
+ cursor.bind_param(:in1, nil, String, 36)
357
+ cursor.bind_param(:in2, nil, :interval_ym)
358
+ [['2006-01-01', -25],
359
+ ['2006-01-01', -24],
360
+ ['2006-01-01', -23],
361
+ ['2006-01-01', -13],
362
+ ['2006-01-01', -12],
363
+ ['2006-01-01', -11],
364
+ ['2006-01-01', +2],
365
+ ['2006-01-01', -2],
366
+ ['2006-01-01', +12]
367
+ ].each do |date, interval|
368
+ cursor[:in1] = date
369
+ cursor[:in2] = interval
370
+ cursor.exec
371
+ assert_equal(DateTime.parse(date) >> interval, DateTime.parse(cursor[:out]))
372
+ end
373
+ cursor.close
374
+ end
375
+
376
+ def test_interval_ds_select
377
+ [['2006-01-01', '2004-03-01'],
378
+ ['2006-01-01', '2005-03-01'],
379
+ ['2006-01-01', '2006-03-01'],
380
+ ['2006-01-01', '2007-03-01'],
381
+ ['2006-01-01', '2006-01-01 23:00:00'],
382
+ ['2006-01-01', '2006-01-01 00:59:00'],
383
+ ['2006-01-01', '2006-01-01 00:00:59'],
384
+ ['2006-01-01', '2006-01-01 00:00:00.999999'],
385
+ ['2006-01-01', '2006-01-01 23:59:59.999999'],
386
+ ['2006-01-01', '2005-12-31 23:00:00'],
387
+ ['2006-01-01', '2005-12-31 00:59:00'],
388
+ ['2006-01-01', '2005-12-31 00:00:59'],
389
+ ['2006-01-01', '2005-12-31 00:00:00.999999'],
390
+ ['2006-01-01', '2005-12-31 23:59:59.999999']
391
+ ].each do |date1, date2|
392
+ @conn.exec(<<-EOS) do |row|
393
+ SELECT (TO_TIMESTAMP('#{date1}', 'YYYY-MM-DD HH24:MI:SS.FF')
394
+ - TO_TIMESTAMP('#{date2}', 'YYYY-MM-DD HH24:MI:SS.FF')) DAY(3) TO SECOND
395
+ FROM dual
396
+ EOS
397
+ assert_in_delta(string_to_time(date1) - string_to_time(date2), row[0], 0.0000000001)
398
+ end
399
+ end
400
+ end
401
+
402
+ def test_interval_ds_out_bind
403
+ cursor = @conn.parse(<<-EOS)
404
+ DECLARE
405
+ ts1 TIMESTAMP;
406
+ ts2 TIMESTAMP;
407
+ BEGIN
408
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD HH24:MI:SS.FF');
409
+ ts2 := TO_TIMESTAMP(:in2, 'YYYY-MM-DD HH24:MI:SS.FF');
410
+ :out := (ts1 - ts2) DAY TO SECOND(9);
411
+ END;
412
+ EOS
413
+ cursor.bind_param(:out, nil, :interval_ds)
414
+ cursor.bind_param(:in1, nil, String, 36)
415
+ cursor.bind_param(:in2, nil, String, 36)
416
+ [['2006-01-01', '2004-03-01'],
417
+ ['2006-01-01', '2005-03-01'],
418
+ ['2006-01-01', '2006-03-01'],
419
+ ['2006-01-01', '2007-03-01'],
420
+ ['2006-01-01', '2006-01-01 23:00:00'],
421
+ ['2006-01-01', '2006-01-01 00:59:00'],
422
+ ['2006-01-01', '2006-01-01 00:00:59'],
423
+ ['2006-01-01', '2006-01-01 00:00:00.999999'],
424
+ ['2006-01-01', '2006-01-01 23:59:59.999999'],
425
+ ['2006-01-01', '2005-12-31 23:00:00'],
426
+ ['2006-01-01', '2005-12-31 00:59:00'],
427
+ ['2006-01-01', '2005-12-31 00:00:59'],
428
+ ['2006-01-01', '2005-12-31 00:00:00.999999'],
429
+ ['2006-01-01', '2005-12-31 23:59:59.999999']
430
+ ].each do |date1, date2|
431
+ cursor[:in1] = date1
432
+ cursor[:in2] = date2
433
+ cursor.exec
434
+ assert_in_delta(string_to_time(date1) - string_to_time(date2), cursor[:out], 0.0000000001)
435
+ end
436
+ cursor.close
437
+ end
438
+
439
+ def test_interval_ds_in_bind
440
+ cursor = @conn.parse(<<-EOS)
441
+ DECLARE
442
+ ts1 TIMESTAMP;
443
+ BEGIN
444
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD HH24:MI:SS.FF');
445
+ :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD HH24:MI:SS.FF');
446
+ END;
447
+ EOS
448
+ cursor.bind_param(:out, nil, String, 36)
449
+ cursor.bind_param(:in1, nil, String, 36)
450
+ cursor.bind_param(:in2, nil, :interval_ds)
451
+ [['2006-01-01', -22],
452
+ ['2006-01-01', -10],
453
+ ['2006-01-01', +2],
454
+ ['2006-01-01', +12],
455
+ ['2006-01-01', -1.to_r / 24], # one hour
456
+ ['2006-01-01', -1.to_r / (24*60)], # one minute
457
+ ['2006-01-01', -1.to_r / (24*60*60)], # one second
458
+ ['2006-01-01', -999999.to_r / (24*60*60*1000000)], # 0.999999 seconds
459
+ ['2006-01-01', +1.to_r / 24], # one hour
460
+ ['2006-01-01', +1.to_r / (24*60)], # one minute
461
+ ['2006-01-01', +1.to_r / (24*60*60)], # one second
462
+ ['2006-01-01', +999999.to_r / (24*60*60*1000000)] # 0.999999 seconds
463
+ ].each do |date, interval|
464
+ interval *= 86400
465
+ cursor[:in1] = date
466
+ cursor[:in2] = interval
467
+ cursor.exec
468
+ assert_equal(string_to_time(date) + interval, string_to_time(cursor[:out]))
469
+ end
470
+ cursor.close
471
+ end
472
+
473
+ def test_days_interval_ds_select
474
+ [['2006-01-01', '2004-03-01'],
475
+ ['2006-01-01', '2005-03-01'],
476
+ ['2006-01-01', '2006-03-01'],
477
+ ['2006-01-01', '2007-03-01'],
478
+ ['2006-01-01', '2006-01-01 23:00:00'],
479
+ ['2006-01-01', '2006-01-01 00:59:00'],
480
+ ['2006-01-01', '2006-01-01 00:00:59'],
481
+ ['2006-01-01', '2006-01-01 00:00:00.999999'],
482
+ ['2006-01-01', '2006-01-01 23:59:59.999999'],
483
+ ['2006-01-01', '2005-12-31 23:00:00'],
484
+ ['2006-01-01', '2005-12-31 00:59:00'],
485
+ ['2006-01-01', '2005-12-31 00:00:59'],
486
+ ['2006-01-01', '2005-12-31 00:00:00.999999'],
487
+ ['2006-01-01', '2005-12-31 23:59:59.999999']
488
+ ].each do |date1, date2|
489
+ begin
490
+ OCI8::BindType::IntervalDS.unit = :day
491
+ @conn.exec(<<-EOS) do |row|
492
+ SELECT (TO_TIMESTAMP('#{date1}', 'YYYY-MM-DD HH24:MI:SS.FF')
493
+ - TO_TIMESTAMP('#{date2}', 'YYYY-MM-DD HH24:MI:SS.FF')) DAY(3) TO SECOND
494
+ FROM dual
495
+ EOS
496
+ assert_equal(DateTime.parse(date1) - DateTime.parse(date2), row[0])
497
+ end
498
+ ensure
499
+ OCI8::BindType::IntervalDS.unit = :second
500
+ end
501
+ end
502
+ end
503
+
504
+ def test_days_interval_ds_out_bind
505
+ cursor = @conn.parse(<<-EOS)
506
+ DECLARE
507
+ ts1 TIMESTAMP;
508
+ ts2 TIMESTAMP;
509
+ BEGIN
510
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD HH24:MI:SS.FF');
511
+ ts2 := TO_TIMESTAMP(:in2, 'YYYY-MM-DD HH24:MI:SS.FF');
512
+ :out := (ts1 - ts2) DAY TO SECOND(9);
513
+ END;
514
+ EOS
515
+ cursor.bind_param(:out, nil, :interval_ds)
516
+ cursor.bind_param(:in1, nil, String, 36)
517
+ cursor.bind_param(:in2, nil, String, 36)
518
+ [['2006-01-01', '2004-03-01'],
519
+ ['2006-01-01', '2005-03-01'],
520
+ ['2006-01-01', '2006-03-01'],
521
+ ['2006-01-01', '2007-03-01'],
522
+ ['2006-01-01', '2006-01-01 23:00:00'],
523
+ ['2006-01-01', '2006-01-01 00:59:00'],
524
+ ['2006-01-01', '2006-01-01 00:00:59'],
525
+ ['2006-01-01', '2006-01-01 00:00:00.999999'],
526
+ ['2006-01-01', '2006-01-01 23:59:59.999999'],
527
+ ['2006-01-01', '2005-12-31 23:00:00'],
528
+ ['2006-01-01', '2005-12-31 00:59:00'],
529
+ ['2006-01-01', '2005-12-31 00:00:59'],
530
+ ['2006-01-01', '2005-12-31 00:00:00.999999'],
531
+ ['2006-01-01', '2005-12-31 23:59:59.999999']
532
+ ].each do |date1, date2|
533
+ begin
534
+ OCI8::BindType::IntervalDS.unit = :day
535
+ cursor[:in1] = date1
536
+ cursor[:in2] = date2
537
+ cursor.exec
538
+ assert_equal(DateTime.parse(date1) - DateTime.parse(date2), cursor[:out])
539
+ ensure
540
+ OCI8::BindType::IntervalDS.unit = :second
541
+ end
542
+ end
543
+ cursor.close
544
+ end
545
+
546
+ def test_days_interval_ds_in_bind
547
+ cursor = @conn.parse(<<-EOS)
548
+ DECLARE
549
+ ts1 TIMESTAMP;
550
+ BEGIN
551
+ ts1 := TO_TIMESTAMP(:in1, 'YYYY-MM-DD');
552
+ :out := TO_CHAR(ts1 + :in2, 'YYYY-MM-DD HH24:MI:SS.FF');
553
+ END;
554
+ EOS
555
+ cursor.bind_param(:out, nil, String, 36)
556
+ cursor.bind_param(:in1, nil, String, 36)
557
+ cursor.bind_param(:in2, nil, :interval_ds)
558
+ [['2006-01-01', -22],
559
+ ['2006-01-01', -10],
560
+ ['2006-01-01', +2],
561
+ ['2006-01-01', +12],
562
+ ['2006-01-01', -1.to_r / 24], # one hour
563
+ ['2006-01-01', -1.to_r / (24*60)], # one minute
564
+ ['2006-01-01', -1.to_r / (24*60*60)], # one second
565
+ ['2006-01-01', -999999.to_r / (24*60*60*1000000)], # 0.999999 seconds
566
+ ['2006-01-01', +1.to_r / 24], # one hour
567
+ ['2006-01-01', +1.to_r / (24*60)], # one minute
568
+ ['2006-01-01', +1.to_r / (24*60*60)], # one second
569
+ ['2006-01-01', +999999.to_r / (24*60*60*1000000)] # 0.999999 seconds
570
+ ].each do |date, interval|
571
+ begin
572
+ OCI8::BindType::IntervalDS.unit = :day
573
+ cursor[:in1] = date
574
+ cursor[:in2] = interval
575
+ cursor.exec
576
+ assert_equal(DateTime.parse(date) + interval, DateTime.parse(cursor[:out]))
577
+ ensure
578
+ OCI8::BindType::IntervalDS.unit = :second
579
+ end
580
+ end
581
+ end
582
+ end # TestOCI8