dt_$foo works for Oracle
[dbsrgits/DBIx-Class.git] / t / sqlmaker / op_dt.t
CommitLineData
5e6893d4 1use strict;
2use warnings;
3
4use Test::More;
fcaf47ee 5use Test::Exception;
5e6893d4 6
7use lib qw(t/lib);
8use DBIC::SqlMakerTest;
9use DateTime;
f94672f9 10use DBIx::Class::SQLMaker::MSSQL;
11use Try::Tiny;
2292bd08 12use Data::Dumper::Concise;
5e6893d4 13
f94672f9 14use DBICTest;
5e6893d4 15
f94672f9 16my %dbs_to_test = (
35621f12 17 sqlite => 1,
18 mssql => 0,
19 postgres => 1,
08c123d2 20 oracle => 1,
f94672f9 21);
22
23my %schema = (
24 sqlite => DBICTest->init_schema( no_populate => 1 ),
25 mssql => do {
26 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PASS/};
27 if ($dsn && $user) {
28 my $s = DBICTest::Schema->connect($dsn, $user, $pass);
29 try { $s->storage->ensure_connected };
5e6893d4 30
f94672f9 31 $s->storage->dbh_do (sub {
32 my ($storage, $dbh) = @_;
33 eval { $dbh->do("DROP TABLE event") };
34 $dbh->do(<<'SQL');
35CREATE TABLE event (
36 id INT IDENTITY NOT NULL,
37 starts_at DATE NOT NULL,
38 created_on DATETIME NOT NULL,
39 varchar_date VARCHAR(20),
40 varchar_datetime VARCHAR(20),
41 skip_inflation DATETIME,
42 ts_without_tz DATETIME,
43
44 primary key(id)
45)
46SQL
47 $dbs_to_test{mssql} = 1;
48});
49$s;
50 } else {
51 DBICTest->init_schema( no_deploy=> 1, storage_type => '::DBI::MSSQL' )
52 }
53 },
35621f12 54 ## copypasta'd for great justice
55 postgres => do {
56 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_POSTGRES_${_}" } qw/DSN USER PASS/};
57 if ($dsn && $user) {
58 my $s = DBICTest::Schema->connect($dsn, $user, $pass);
59 try { $s->storage->ensure_connected };
60
61 $s->storage->dbh_do (sub {
62 my ($storage, $dbh) = @_;
63 eval { $dbh->do("DROP TABLE event") };
64 $dbh->do(<<'SQL');
65CREATE TABLE event (
66 id SERIAL NOT NULL PRIMARY KEY,
67 starts_at DATE NOT NULL,
68 created_on TIMESTAMP NOT NULL,
69 varchar_date VARCHAR(20),
70 varchar_datetime VARCHAR(20),
71 skip_inflation TIMESTAMP,
72 ts_without_tz TIMESTAMP WITHOUT TIME ZONE
73)
74SQL
75 $dbs_to_test{postgres} = 1;
76});
77$s;
78 } else {
79 DBICTest->init_schema( no_deploy=> 1, storage_type => '::DBI::Pg' )
80 }
08c123d2 81 },
82 oracle => do {
83 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_ORA_${_}" } qw/DSN USER PASS/};
84 if ($dsn && $user) {
85 my $s = DBICTest::Schema->connect($dsn, $user, $pass, { on_connect_call => 'datetime_setup' });
86 try { $s->storage->ensure_connected };
87
88 $s->storage->dbh_do (sub {
89 my ($storage, $dbh) = @_;
90 eval { $dbh->do("DROP TRIGGER trq_event_id") };
91 eval { $dbh->do("DROP SEQUENCE sq_event_id") };
92 eval { $dbh->do("DROP TABLE event") };
93 $dbh->do('CREATE SEQUENCE sq_event_id');
94 $dbh->do(<<'SQL');
95CREATE TABLE event (
96 id NUMBER NOT NULL,
97 starts_at DATE NOT NULL,
98 created_on TIMESTAMP NOT NULL,
99 varchar_date VARCHAR(20),
100 varchar_datetime VARCHAR(20),
101 skip_inflation TIMESTAMP,
102 ts_without_tz TIMESTAMP,
103 CONSTRAINT PK_EVENT PRIMARY KEY (id)
104)
105SQL
106 $dbh->do(<<'SQL');
107CREATE TRIGGER trg_event_id
108BEFORE INSERT ON event
109FOR EACH ROW WHEN (
110 new.id IS NULL OR new.id = 0
111)
112BEGIN
113 SELECT sq_event_id.nextval
114 INTO :new.id
115 FROM dual;
116 END;
117SQL
118 $dbs_to_test{oracle} = 1;
119});
120$s;
121 } else {
122 DBICTest->init_schema( no_deploy=> 1, storage_type => '::DBI::Oracle', on_connect_call => 'datetime_setup' )
123 }
124 },
fcaf47ee 125);
5e6893d4 126
f94672f9 127my %rs = map { $_ => $schema{$_}->resultset('Event') } keys %schema;
128
129$rs{sqlite}->populate([
130 [qw(starts_at created_on skip_inflation)],
131 ['2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12'],
132 ['2010-12-12', '2011-12-14 12:12:12', '2011-12-12 12:12:12'],
133]);
134
135$rs{mssql}->populate([
136 [qw(starts_at created_on skip_inflation)],
137 ['2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000'],
138 ['2010-12-12', '2011-12-14 12:12:12.000', '2011-12-12 12:12:12.000'],
139]) if $schema{mssql}->storage->connected;
140
35621f12 141$rs{postgres}->populate([
142 [qw(starts_at created_on skip_inflation)],
143 ['2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12'],
144 ['2010-12-12', '2011-12-14 12:12:12', '2011-12-12 12:12:12'],
145]) if $schema{postgres}->storage->connected;
146
08c123d2 147$rs{oracle}->populate([
148 [qw(starts_at created_on skip_inflation)],
149 ['2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12'],
150 ['2010-12-12', '2011-12-14 12:12:12', '2011-12-12 12:12:12'],
151]) if $schema{oracle}->storage->connected;
35621f12 152
5e6893d4 153my $date = DateTime->new(
154 year => 2010,
155 month => 12,
156 day => 14,
157 hour => 12,
158 minute => 12,
159 second => 12,
160);
161
f94672f9 162sub hri_thing {
163 return {
164 starts_at => $_[0],
165 created_on => $_[1],
166 skip_inflation => $_[2]
167 }
168}
169
5e6893d4 170my $date2 = $date->clone->set_day(16);
171
35621f12 172## test format:
173## search => { dbic_search_code/params }
174## rdbms_name => literal_sql
fcaf47ee 175my @tests = (
35621f12 176## -dt-now tests
fcaf47ee 177 {
f94672f9 178 search => { 'me.created_on' => { -dt => $date } },
fcaf47ee 179 sqlite => {
f94672f9 180 select => 'me.starts_at, me.created_on, me.skip_inflation',
181 where => 'me.created_on = ?',
182 bind => [[ 'me.created_on', '2010-12-14 12:12:12' ]],
183 hri => [hri_thing('2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12')],
fcaf47ee 184 },
f94672f9 185 mssql => {
186 select => 'me.starts_at, me.created_on, me.skip_inflation',
187 where => 'me.created_on = ?',
188 bind => [[ 'me.created_on', '2010-12-14 12:12:12.000' ]],
189 hri => [hri_thing('2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000')],
fcaf47ee 190 },
35621f12 191 postgres => {
192 select => 'me.starts_at, me.created_on, me.skip_inflation',
193 where => 'me.created_on = ?',
194 bind => [[ 'me.created_on', '2010-12-14 12:12:12' ]],
195 hri => [hri_thing('2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12')],
196 },
08c123d2 197 oracle => {
198 select => 'me.starts_at, me.created_on, me.skip_inflation',
199 where => 'me.created_on = ?',
200 bind => [[ 'me.created_on', '2010-12-14 12:12:12' ]],
201 hri => [hri_thing('2010-12-12 00:00:00', '2010-12-14 12:12:12.000000', '2019-12-12 12:12:12.000000')],
202 },
fcaf47ee 203 msg => '-dt_now works',
204 },
35621f12 205## -dt_year tests
fcaf47ee 206 {
f94672f9 207 search => { 'me.id' => 1 },
208 select => [ [ -dt_year => { -ident => 'me.created_on' } ] ],
209 as => [ 'year' ],
210 mssql => {
211 select => "DATEPART(year, me.created_on)",
212 where => "me.id = ?",
213 bind => [['me.id' => 1 ]],
214 hri => [{ year => 2010 }],
215 },
fcaf47ee 216 sqlite => {
f94672f9 217 select => "STRFTIME('%Y', me.created_on)",
218 where => "me.id = ?",
219 bind => [['me.id' => 1 ]],
220 hri => [{ year => 2010 }],
fcaf47ee 221 },
35621f12 222 postgres => {
223 select => "EXTRACT(year FROM me.created_on)",
224 where => "me.id = ?",
225 bind => [['me.id' => 1 ]],
226 hri => [{ year => 2010 }],
227 },
08c123d2 228 oracle => {
229 select => "EXTRACT(year FROM me.created_on)",
230 where => "me.id = ?",
231 bind => [['me.id' => 1 ]],
232 hri => [{ year => 2010 }],
233 },
fcaf47ee 234 msg => '-dt_year works',
235 },
35621f12 236## -dt_get(year, month) tests
fcaf47ee 237 {
f94672f9 238 search => { 'me.id' => 1 },
464a9709 239 select => [ [ -dt_get => [[qw(year month)], { -ident => 'me.created_on' }] ] ],
240 as => [ qw(year month) ],
241 mssql => {
242 select => "DATEPART(year, me.created_on), DATEPART(month, me.created_on)",
243 where => "me.id = ?",
244 bind => [['me.id' => 1 ]],
245 hri => [{ year => 2010, month => 12 }],
246 },
247 sqlite => {
248 select => "STRFTIME('%Y', me.created_on), STRFTIME('%m', me.created_on)",
249 where => "me.id = ?",
250 bind => [['me.id' => 1 ]],
251 hri => [{ year => 2010, month => 12 }],
252 },
35621f12 253 postgres => {
254 select => "EXTRACT(year FROM me.created_on), EXTRACT(month FROM me.created_on)",
255 where => "me.id = ?",
256 bind => [['me.id' => 1 ]],
257 hri => [{ year => 2010, month => 12 }],
258 },
08c123d2 259 oracle => {
260 select => "EXTRACT(year FROM me.created_on), EXTRACT(month FROM me.created_on)",
261 where => "me.id = ?",
262 bind => [['me.id' => 1 ]],
263 hri => [{ year => 2010, month => 12 }],
264 },
464a9709 265 msg => '-dt_get (year, month) works',
266 },
35621f12 267## -dt_month tests
464a9709 268 {
269 search => { 'me.id' => 1 },
f94672f9 270 select => [ [ -dt_month => { -ident => 'me.created_on' } ] ],
271 as => [ 'month' ],
fcaf47ee 272 sqlite => {
f94672f9 273 select => "STRFTIME('%m', me.created_on)",
274 where => "me.id = ?",
275 bind => [['me.id' => 1 ]],
276 hri => [{ month => 12 }],
277 },
278 mssql => {
279 select => "DATEPART(month, me.created_on)",
280 where => "me.id = ?",
281 bind => [['me.id' => 1 ]],
282 hri => [{ month => 12 }],
fcaf47ee 283 },
35621f12 284 postgres => {
285 select => "EXTRACT(month FROM me.created_on)",
286 where => "me.id = ?",
287 bind => [['me.id' => 1 ]],
288 hri => [{ month => 12 }],
08c123d2 289 },
290 oracle => {
291 select => "EXTRACT(month FROM me.created_on)",
292 where => "me.id = ?",
293 bind => [['me.id' => 1 ]],
294 hri => [{ month => 12 }],
35621f12 295 },
fcaf47ee 296 msg => '-dt_month works',
297 },
35621f12 298## -dt_day tests
fcaf47ee 299 {
f94672f9 300 search => { 'me.id' => 1 },
301 select => [ [ -dt_day => { -ident => 'me.created_on' } ] ],
302 as => [ 'day' ],
fcaf47ee 303 sqlite => {
f94672f9 304 select => "STRFTIME('%d', me.created_on)",
305 where => "me.id = ?",
306 bind => [['me.id' => 1 ]],
307 hri => [{ day => 14 }],
308 },
309 mssql => {
310 select => "DATEPART(day, me.created_on)",
311 where => "me.id = ?",
312 bind => [['me.id' => 1 ]],
313 hri => [{ day => 14 }],
fcaf47ee 314 },
35621f12 315 postgres => {
316 select => "EXTRACT(day FROM me.created_on)",
317 where => "me.id = ?",
318 bind => [['me.id' => 1 ]],
319 hri => [{ day => 14 }],
08c123d2 320 },
321 oracle => {
322 select => "EXTRACT(day FROM me.created_on)",
323 where => "me.id = ?",
324 bind => [['me.id' => 1 ]],
325 hri => [{ day => 14 }],
35621f12 326 },
fcaf47ee 327 msg => '-dt_day works',
328 },
35621f12 329## -dt_hour tests
fcaf47ee 330 {
f94672f9 331 search => { 'me.id' => 1 },
332 select => [ [ -dt_hour => { -ident => 'me.created_on' } ] ],
333 as => [ 'hour' ],
fcaf47ee 334 sqlite => {
f94672f9 335 select => "STRFTIME('%H', me.created_on)",
336 where => "me.id = ?",
337 bind => [['me.id' => 1 ]],
338 hri => [{ hour => 12 }],
339 },
340 mssql => {
341 select => "DATEPART(hour, me.created_on)",
342 where => "me.id = ?",
343 bind => [['me.id' => 1 ]],
344 hri => [{ hour => 12 }],
fcaf47ee 345 },
35621f12 346 postgres => {
347 select => "EXTRACT(hour FROM me.created_on)",
348 where => "me.id = ?",
349 bind => [['me.id' => 1 ]],
350 hri => [{ hour => 12 }],
351 },
08c123d2 352 oracle => {
353 select => "EXTRACT(hour FROM me.created_on)",
354 where => "me.id = ?",
355 bind => [['me.id' => 1 ]],
356 hri => [{ hour => 12 }],
357 },
fcaf47ee 358 msg => '-dt_hour works',
359 },
35621f12 360## -dt_minute tests
fcaf47ee 361 {
f94672f9 362 search => { 'me.id' => 1 },
363 select => [ [ -dt_minute => { -ident => 'me.created_on' } ] ],
364 as => [ 'minute' ],
fcaf47ee 365 sqlite => {
f94672f9 366 select => "STRFTIME('%M', me.created_on)",
367 where => "me.id = ?",
368 bind => [['me.id' => 1 ]],
369 hri => [{ minute => 12 }],
370 },
371 mssql => {
372 select => "DATEPART(minute, me.created_on)",
373 where => "me.id = ?",
374 bind => [['me.id' => 1 ]],
375 hri => [{ minute => 12 }],
fcaf47ee 376 },
35621f12 377 postgres => {
378 select => "EXTRACT(minute FROM me.created_on)",
379 where => "me.id = ?",
380 bind => [['me.id' => 1 ]],
381 hri => [{ minute => 12 }],
382 },
08c123d2 383 oracle => {
384 select => "EXTRACT(minute FROM me.created_on)",
385 where => "me.id = ?",
386 bind => [['me.id' => 1 ]],
387 hri => [{ minute => 12 }],
388 },
fcaf47ee 389 msg => '-dt_minute works',
390 },
35621f12 391## -dt_second tests
fcaf47ee 392 {
f94672f9 393 search => { 'me.id' => 1 },
394 select => [ [ -dt_second => { -ident => 'me.created_on' } ] ],
395 as => [ 'second' ],
fcaf47ee 396 sqlite => {
f94672f9 397 select => "STRFTIME('%S', me.created_on)",
398 where => "me.id = ?",
399 bind => [['me.id' => 1 ]],
400 hri => [{ second => 12 }],
401 },
402 mssql => {
403 select => "DATEPART(second, me.created_on)",
404 where => "me.id = ?",
405 bind => [['me.id' => 1 ]],
406 hri => [{ second => 12 }],
fcaf47ee 407 },
35621f12 408 postgres => {
409 select => "EXTRACT(second FROM me.created_on)",
410 where => "me.id = ?",
411 bind => [['me.id' => 1 ]],
412 hri => [{ second => 12 }],
08c123d2 413 },
414 oracle => {
415 select => "EXTRACT(second FROM me.created_on)",
416 where => "me.id = ?",
417 bind => [['me.id' => 1 ]],
418 hri => [{ second => 12 }],
35621f12 419 },
fcaf47ee 420 msg => '-dt_second works',
421 },
35621f12 422## -dt_diff(second) tests
fcaf47ee 423 {
f94672f9 424 search => { 'me.id' => 2 },
425 select => [ [ -dt_diff => [second => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
426 as => [ 'sec_diff' ],
fcaf47ee 427 sqlite => {
f94672f9 428 select => "(STRFTIME('%s', me.created_on) - STRFTIME('%s', me.skip_inflation))",
429 where => "me.id = ?",
430 bind => [['me.id' => 2 ]],
431 hri => [{ sec_diff => 2*24*60*60 }],
432 },
433 mssql => {
434 select => "DATEDIFF(second, me.skip_inflation, me.created_on)",
435 where => "me.id = ?",
436 bind => [['me.id' => 2 ]],
437 hri => [{ sec_diff => 2*24*60*60 }],
fcaf47ee 438 },
35621f12 439 postgres => {
440 select => "EXTRACT(epoch FROM (me.created_on::timestamp with time zone - me.skip_inflation::timestamp with time zone))",
441 where => "me.id = ?",
442 bind => [['me.id' => 2 ]],
443 hri => [{ sec_diff => 2*24*60*60 }],
444 },
08c123d2 445 oracle => {
446 select => "TRUNC(MONTHS_BETWEEN(me.created_on, me.skip_inflation) * 31 * 24 * 60 * 60)",
447 where => "me.id = ?",
448 bind => [['me.id' => 2 ]],
449 hri => [{ sec_diff => 2*24*60*60 }],
450 },
fcaf47ee 451 msg => '-dt_diff (second) works',
452 },
f94672f9 453
35621f12 454# -dt_diff(day) tests
fcaf47ee 455 {
f94672f9 456 search => { 'me.id' => 2 },
457 select => [ [ -dt_diff => [day => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
458 as => [ 'day_diff' ],
fcaf47ee 459 sqlite => {
f94672f9 460 select => "(JULIANDAY(me.created_on) - JULIANDAY(me.skip_inflation))",
461 where => "me.id = ?",
462 bind => [['me.id' => 2 ]],
463 hri => [{ day_diff => 2 }],
464 },
465 mssql => {
466 select => "DATEDIFF(dayofyear, me.skip_inflation, me.created_on)",
467 where => "me.id = ?",
468 bind => [['me.id' => 2 ]],
469 hri => [{ day_diff => 2 }],
fcaf47ee 470 },
35621f12 471 postgres => {
472 select => "EXTRACT(DAY FROM (me.created_on::timestamp with time zone - me.skip_inflation::timestamp with time zone))",
473 where => "me.id = ?",
474 bind => [['me.id' => 2 ]],
475 hri => [{ day_diff => 2 }],
476 },
08c123d2 477 oracle => {
478 select => "TRUNC(MONTHS_BETWEEN(me.created_on, me.skip_inflation) * 31)",
479 where => "me.id = ?",
480 bind => [['me.id' => 2 ]],
481 hri => [{ day_diff => 2 }],
482 },
fcaf47ee 483 msg => '-dt_diff (day) works',
484 },
f94672f9 485
fcaf47ee 486 {
08c123d2 487 msg => '-dt_add (year) works',
f94672f9 488 search => { 'me.id' => 2 },
489 select => [ [ -dt_add => [year => 3, { -ident => 'me.created_on' } ] ] ],
490 as => [ 'date' ],
fcaf47ee 491 sqlite => {
f94672f9 492 select => "(datetime(me.created_on, ? || ' years'))",
493 where => "me.id = ?",
494 bind => [['', 3], ['me.id' => 2 ]],
495 hri => [{ date => '2014-12-14 12:12:12' }],
496 },
497 mssql => {
498 select => "(DATEADD(year, ?, me.created_on))",
499 where => "me.id = ?",
500 bind => [['', 3], ['me.id' => 2 ]],
501 hri => [{ date => '2014-12-14 12:12:12.000' }],
502 skip => 'need working bindtypes',
fcaf47ee 503 },
08c123d2 504 oracle => {
505 select => "(me.created_on + NUMTOYMINTERVAL(?, 'year'))",
506 where => "me.id = ?",
507 bind => [['', 3], ['me.id' => 2 ]],
508 hri => [{ date => '2014-12-14 12:12:12.000000000' }],
509 },
fcaf47ee 510 },
f94672f9 511
fcaf47ee 512 {
08c123d2 513 msg => '-dt_add (month) works',
f94672f9 514 search => { 'me.id' => 2 },
515 select => [ [ -dt_add => [month => 3, { -ident => 'me.created_on' } ] ] ],
516 as => [ 'date' ],
fcaf47ee 517 sqlite => {
f94672f9 518 select => "(datetime(me.created_on, ? || ' months'))",
519 where => "me.id = ?",
520 bind => [['', 3], ['me.id' => 2 ]],
521 hri => [{ date => '2012-03-14 12:12:12' }],
522 },
523 mssql => {
524 select => "(DATEADD(month, ?, me.created_on))",
525 where => "me.id = ?",
526 bind => [['', 3], ['me.id' => 2 ]],
527 hri => [{ date => '2012-03-14 12:12:12.000' }],
528 skip => 'need working bindtypes',
fcaf47ee 529 },
08c123d2 530 oracle => {
531 select => "(me.created_on + NUMTOYMINTERVAL(?, 'month'))",
532 where => "me.id = ?",
533 bind => [['', 3], ['me.id' => 2 ]],
534 hri => [{ date => '2012-03-14 12:12:12.000000000' }],
535 },
fcaf47ee 536 },
f94672f9 537
fcaf47ee 538 {
08c123d2 539 msg => '-dt_add (day) works',
f94672f9 540 search => { 'me.id' => 2 },
541 select => [ [ -dt_add => [day => 3, { -ident => 'me.created_on' } ] ] ],
542 as => [ 'date' ],
fcaf47ee 543 sqlite => {
f94672f9 544 select => "(datetime(me.created_on, ? || ' days'))",
545 where => "me.id = ?",
546 bind => [['', 3], ['me.id' => 2 ]],
547 hri => [{ date => '2011-12-17 12:12:12' }],
548 },
549 mssql => {
550 select => "(DATEADD(dayofyear, ?, me.created_on))",
551 where => "me.id = ?",
552 bind => [['', 3], ['me.id' => 2 ]],
553 hri => [{ date => '2011-12-17 12:12:12.000' }],
554 skip => 'need working bindtypes',
fcaf47ee 555 },
08c123d2 556 oracle => {
557 select => "(me.created_on + NUMTODSINTERVAL(?, 'day'))",
558 where => "me.id = ?",
559 bind => [['', 3], ['me.id' => 2 ]],
560 hri => [{ date => '2011-12-17 12:12:12.000000000' }],
561 },
fcaf47ee 562 },
f94672f9 563
fcaf47ee 564 {
08c123d2 565 msg => '-dt_add (hour) works',
f94672f9 566 search => { 'me.id' => 2 },
567 select => [ [ -dt_add => [hour => 3, { -ident => 'me.created_on' } ] ] ],
568 as => [ 'date' ],
fcaf47ee 569 sqlite => {
f94672f9 570 select => "(datetime(me.created_on, ? || ' hours'))",
571 where => "me.id = ?",
572 bind => [['', 3], ['me.id' => 2 ]],
573 hri => [{ date => '2011-12-14 15:12:12' }],
574 },
575 mssql => {
576 select => "(DATEADD(hour, ?, me.created_on))",
577 where => "me.id = ?",
578 bind => [['', 3], ['me.id' => 2 ]],
579 hri => [{ date => '2011-12-14 15:12:12.000' }],
580 skip => 'need working bindtypes',
fcaf47ee 581 },
08c123d2 582 oracle => {
583 select => "(me.created_on + NUMTODSINTERVAL(?, 'hour'))",
584 where => "me.id = ?",
585 bind => [['', 3], ['me.id' => 2 ]],
586 hri => [{ date => '2011-12-14 15:12:12.000000000' }],
587 },
fcaf47ee 588 },
f94672f9 589
fcaf47ee 590 {
08c123d2 591 msg => '-dt_add (minute) works',
f94672f9 592 search => { 'me.id' => 2 },
593 select => [ [ -dt_add => [minute => 3, { -ident => 'me.created_on' } ] ] ],
594 as => [ 'date' ],
fcaf47ee 595 sqlite => {
f94672f9 596 select => "(datetime(me.created_on, ? || ' minutes'))",
597 where => "me.id = ?",
598 bind => [['', 3], ['me.id' => 2 ]],
599 hri => [{ date => '2011-12-14 12:15:12' }],
600 },
601 mssql => {
602 select => "(DATEADD(minute, ?, me.created_on))",
603 where => "me.id = ?",
604 bind => [['', 3], ['me.id' => 2 ]],
605 hri => [{ date => '2011-12-14 12:15:12.000' }],
606 skip => 'need working bindtypes',
fcaf47ee 607 },
08c123d2 608 oracle => {
609 select => "(me.created_on + NUMTODSINTERVAL(?, 'minute'))",
610 where => "me.id = ?",
611 bind => [['', 3], ['me.id' => 2 ]],
612 hri => [{ date => '2011-12-14 12:15:12.000000000' }],
613 },
fcaf47ee 614 },
f94672f9 615
fcaf47ee 616 {
08c123d2 617 msg => '-dt_add (second) works',
f94672f9 618 search => { 'me.id' => 2 },
619 select => [ [ -dt_add => [second => 3, { -ident => 'me.created_on' } ] ] ],
620 as => [ 'date' ],
fcaf47ee 621 sqlite => {
f94672f9 622 select => "(datetime(me.created_on, ? || ' seconds'))",
623 where => "me.id = ?",
624 bind => [['', 3], ['me.id' => 2 ]],
625 hri => [{ date => '2011-12-14 12:12:15' }],
626 },
627 mssql => {
628 select => "(DATEADD(second, ?, me.created_on))",
629 where => "me.id = ?",
630 bind => [['', 3], ['me.id' => 2 ]],
631 hri => [{ date => '2011-12-14 12:12:15.000' }],
632 skip => 'need working bindtypes',
fcaf47ee 633 },
08c123d2 634 oracle => {
635 select => "(me.created_on + NUMTODSINTERVAL(?, 'second'))",
636 where => "me.id = ?",
637 bind => [['', 3], ['me.id' => 2 ]],
638 hri => [{ date => '2011-12-14 12:12:15.000000000' }],
639 },
fcaf47ee 640 },
f94672f9 641
fcaf47ee 642 {
08c123d2 643 msg => 'nested -dt_add works',
f94672f9 644 search => { 'me.id' => 2 },
645 select => [ [ -dt_add => [second => 3, { -dt_add => [ day => 1, { -ident => 'me.created_on' } ] } ] ] ],
646 as => [ 'date' ],
647 sqlite => {
648 select => "(datetime((datetime(me.created_on, ? || ' days')), ? || ' seconds'))",
649 where => "me.id = ?",
650 bind => [['', 1], [ '', 3 ], ['me.id', 2]],
651 hri => [{ date => '2011-12-15 12:12:15' }],
652 },
653 mssql => {
654 select => "(DATEADD(second, ?, (DATEADD(dayofyear, ?, me.created_on))))",
655 where => "me.id = ?",
656 bind => [['', 3], [ '', 1 ], ['me.id', 2]],
657 hri => [{ date => '2011-12-15 12:12:15.000' }],
658 skip => 'need working bindtypes',
659 },
08c123d2 660 oracle => {
661 select => "((me.created_on + NUMTODSINTERVAL(?, 'day')) + NUMTODSINTERVAL(?, 'second'))",
662 where => "me.id = ?",
663 bind => [['', 1], [ '', 3 ], ['me.id', 2]],
664 hri => [{ date => '2011-12-15 12:12:15.000000000' }],
665 },
f94672f9 666 },
667
668 {
08c123d2 669 msg => '-dt_diff (year) works',
f94672f9 670 search => { 'me.id' => 2 },
671 select => [ [ -dt_diff => [year => \'me.starts_at', { -ident => 'me.created_on' } ] ] ],
672 as => [ 'year' ],
fcaf47ee 673 sqlite => {
674 exception_like => qr/date diff not supported for part "year" with database "SQLite"/,
675 },
f94672f9 676 mssql => {
677 select => "DATEDIFF(year, me.created_on, me.starts_at)",
678 where => "me.id = ?",
679 bind => [['me.id', 2]],
680 hri => [{ year => -1 }],
681 },
08c123d2 682 oracle => {
683 select => "TRUNC(MONTHS_BETWEEN(me.starts_at, me.created_on) / 12)",
684 where => "me.id = ?",
685 bind => [['me.id', 2]],
686 hri => [{ year => -1 }],
687 },
fcaf47ee 688 },
689);
5a44a8ec 690
fcaf47ee 691for my $t (@tests) {
5a44a8ec 692
fcaf47ee 693 DB_TEST:
f94672f9 694 for my $db (keys %rs) {
fcaf47ee 695 my $db_test = $t->{$db};
696 next DB_TEST unless $db_test;
5e6893d4 697
f94672f9 698 my ($r, $my_rs);
fcaf47ee 699
700 my $cref = sub {
f94672f9 701 my $stuff = {
702 ( exists $t->{select}
703 ? ( select => $t->{select}, as => $t->{as} )
704 : ( columns => [qw(starts_at created_on skip_inflation)] )
705 )
706 };
707 $my_rs = $rs{$db}->search($t->{search}, $stuff);
708 $r = $my_rs->as_query
fcaf47ee 709 };
5e6893d4 710
fcaf47ee 711 if ($db_test->{exception_like}) {
712 throws_ok(
713 sub { $cref->() },
714 $db_test->{exception_like},
715 "throws the expected exception ($db_test->{exception_like})",
716 );
717 } else {
718 if ($db_test->{warning_like}) {
719 warning_like(
720 sub { $cref->() },
721 $db_test->{warning_like},
722 "issues the expected warning ($db_test->{warning_like})"
723 );
724 }
725 else {
726 $cref->();
727 }
728 is_same_sql_bind(
f94672f9 729 $r,
730 "(SELECT $db_test->{select} FROM event me WHERE $db_test->{where})",
fcaf47ee 731 $db_test->{bind},
f94672f9 732 ($t->{msg} ? "$t->{msg} ($db)" : ())
fcaf47ee 733 );
f94672f9 734
735 SKIP: {
736 if (my $hri = $db_test->{hri}) {
737 skip "Cannot test database we are not connected to ($db)", 1 unless $dbs_to_test{$db};
738 skip $db_test->{skip} . " ($db)", 1 if $db_test->{skip};
739
740 my $msg = ($t->{msg} ? "$t->{msg} ($db actually pulls expected data)" : '');
741 try {
2292bd08 742 my $got = [ $my_rs->hri_dump->all ];
743 my $success = is_deeply $got, $hri, $msg;
744 unless ($success) {
745 warn "$db: $t->{msg} got: " . Dumper $got;
746 warn "$db: $t->{msg} expected: " . Dumper $hri;
747 }
f94672f9 748 } catch {
749 ok 0, $msg . " $_";
750 }
751 } }
fcaf47ee 752 }
753 }
754}
6edb8b2f 755
5e6893d4 756done_testing;