use lib qw(t/lib);
use DBIC::SqlMakerTest;
use DateTime;
+use DBIx::Class::SQLMaker::MSSQL;
+use Try::Tiny;
-use_ok('DBICTest');
+use DBICTest;
-my $schema = DBICTest->init_schema();
+my %dbs_to_test = (
+ sqlite => 1,
+ mssql => 0,
+);
+
+my %schema = (
+ sqlite => DBICTest->init_schema( no_populate => 1 ),
+ mssql => do {
+ my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PASS/};
+ if ($dsn && $user) {
+ my $s = DBICTest::Schema->connect($dsn, $user, $pass);
+ try { $s->storage->ensure_connected };
-my %sql_maker = (
- sqlite => $schema->storage->sql_maker,
+ $s->storage->dbh_do (sub {
+ my ($storage, $dbh) = @_;
+ eval { $dbh->do("DROP TABLE event") };
+ $dbh->do(<<'SQL');
+CREATE TABLE event (
+ id INT IDENTITY NOT NULL,
+ starts_at DATE NOT NULL,
+ created_on DATETIME NOT NULL,
+ varchar_date VARCHAR(20),
+ varchar_datetime VARCHAR(20),
+ skip_inflation DATETIME,
+ ts_without_tz DATETIME,
+
+ primary key(id)
+)
+SQL
+ $dbs_to_test{mssql} = 1;
+});
+$s;
+ } else {
+ DBICTest->init_schema( no_deploy=> 1, storage_type => '::DBI::MSSQL' )
+ }
+ },
);
+my %rs = map { $_ => $schema{$_}->resultset('Event') } keys %schema;
+
+$rs{sqlite}->populate([
+ [qw(starts_at created_on skip_inflation)],
+ ['2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12'],
+ ['2010-12-12', '2011-12-14 12:12:12', '2011-12-12 12:12:12'],
+]);
+
+$rs{mssql}->populate([
+ [qw(starts_at created_on skip_inflation)],
+ ['2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000'],
+ ['2010-12-12', '2011-12-14 12:12:12.000', '2011-12-12 12:12:12.000'],
+]) if $schema{mssql}->storage->connected;
+
+#my %sql_maker = map { $_ => $schema{$_}->storage->sql_maker } keys %schema;
+
my $date = DateTime->new(
year => 2010,
month => 12,
second => 12,
);
+sub hri_thing {
+ return {
+ starts_at => $_[0],
+ created_on => $_[1],
+ skip_inflation => $_[2]
+ }
+}
+
my $date2 = $date->clone->set_day(16);
my @tests = (
{
- func => 'select',
- args => ['artist', '*', { 'artist.when_began' => { -dt => $date } }],
+ search => { 'me.created_on' => { -dt => $date } },
sqlite => {
- stmt => 'SELECT * FROM artist WHERE artist.when_began = ?',
- bind => [[ 'artist.when_began', '2010-12-14 12:12:12' ]],
+ select => 'me.starts_at, me.created_on, me.skip_inflation',
+ where => 'me.created_on = ?',
+ bind => [[ 'me.created_on', '2010-12-14 12:12:12' ]],
+ hri => [hri_thing('2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12')],
},
- msg => '-dt_now works',
- },
- {
- func => 'update',
- args => ['artist',
- { 'artist.when_began' => { -dt => $date } },
- { 'artist.when_ended' => { '<' => { -dt => $date2 } } }
- ],
- sqlite => {
- stmt => 'UPDATE artist SET artist.when_began = ? WHERE artist.when_ended < ? ',
- bind => [
- [ 'artist.when_began', '2010-12-14 12:12:12' ],
- [ 'artist.when_ended', '2010-12-16 12:12:12' ],
- ],
+ mssql => {
+ select => 'me.starts_at, me.created_on, me.skip_inflation',
+ where => 'me.created_on = ?',
+ bind => [[ 'me.created_on', '2010-12-14 12:12:12.000' ]],
+ hri => [hri_thing('2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000')],
},
msg => '-dt_now works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_year => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_year => { -ident => 'me.created_on' } ] ],
+ as => [ 'year' ],
+ mssql => {
+ select => "DATEPART(year, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ year => 2010 }],
+ },
sqlite => {
- stmt => "SELECT STRFTIME('%Y', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%Y', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ year => 2010 }],
},
msg => '-dt_year works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_month => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_month => { -ident => 'me.created_on' } ] ],
+ as => [ 'month' ],
sqlite => {
- stmt => "SELECT STRFTIME('%m', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%m', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ month => 12 }],
+ },
+ mssql => {
+ select => "DATEPART(month, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ month => 12 }],
},
msg => '-dt_month works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_day => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_day => { -ident => 'me.created_on' } ] ],
+ as => [ 'day' ],
sqlite => {
- stmt => "SELECT STRFTIME('%d', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%d', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ day => 14 }],
+ },
+ mssql => {
+ select => "DATEPART(day, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ day => 14 }],
},
msg => '-dt_day works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_hour => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_hour => { -ident => 'me.created_on' } ] ],
+ as => [ 'hour' ],
sqlite => {
- stmt => "SELECT STRFTIME('%H', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%H', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ hour => 12 }],
+ },
+ mssql => {
+ select => "DATEPART(hour, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ hour => 12 }],
},
msg => '-dt_hour works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_minute => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_minute => { -ident => 'me.created_on' } ] ],
+ as => [ 'minute' ],
sqlite => {
- stmt => "SELECT STRFTIME('%M', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%M', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ minute => 12 }],
+ },
+ mssql => {
+ select => "DATEPART(minute, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ minute => 12 }],
},
msg => '-dt_minute works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_second => { -ident => 'artist.when_began' } ] ]],
+ search => { 'me.id' => 1 },
+ select => [ [ -dt_second => { -ident => 'me.created_on' } ] ],
+ as => [ 'second' ],
sqlite => {
- stmt => "SELECT STRFTIME('%s', artist.when_began) FROM artist",
- bind => [],
+ select => "STRFTIME('%S', me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ second => 12 }],
+ },
+ mssql => {
+ select => "DATEPART(second, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 1 ]],
+ hri => [{ second => 12 }],
},
msg => '-dt_second works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_diff => [second => { -ident => 'artist.when_ended' }, \'artist.when_began' ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_diff => [second => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
+ as => [ 'sec_diff' ],
sqlite => {
- stmt => "SELECT (STRFTIME('%s', artist.when_ended) - STRFTIME('%s', artist.when_began)) FROM artist",
- bind => [],
+ select => "(STRFTIME('%s', me.created_on) - STRFTIME('%s', me.skip_inflation))",
+ where => "me.id = ?",
+ bind => [['me.id' => 2 ]],
+ hri => [{ sec_diff => 2*24*60*60 }],
+ },
+ mssql => {
+ select => "DATEDIFF(second, me.skip_inflation, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 2 ]],
+ hri => [{ sec_diff => 2*24*60*60 }],
},
msg => '-dt_diff (second) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_diff => [day => { -ident => 'artist.when_ended' }, \'artist.when_began' ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_diff => [day => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
+ as => [ 'day_diff' ],
sqlite => {
- stmt => "SELECT (JULIANDAY(artist.when_ended) - JULIANDAY(artist.when_began)) FROM artist",
- bind => [],
+ select => "(JULIANDAY(me.created_on) - JULIANDAY(me.skip_inflation))",
+ where => "me.id = ?",
+ bind => [['me.id' => 2 ]],
+ hri => [{ day_diff => 2 }],
+ },
+ mssql => {
+ select => "DATEDIFF(dayofyear, me.skip_inflation, me.created_on)",
+ where => "me.id = ?",
+ bind => [['me.id' => 2 ]],
+ hri => [{ day_diff => 2 }],
},
msg => '-dt_diff (day) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [year => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [year => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' years')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' years'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2014-12-14 12:12:12' }],
+ },
+ mssql => {
+ select => "(DATEADD(year, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2014-12-14 12:12:12.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (year) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [month => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [month => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' months')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' months'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2012-03-14 12:12:12' }],
+ },
+ mssql => {
+ select => "(DATEADD(month, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2012-03-14 12:12:12.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (month) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [day => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [day => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' days')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' days'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-17 12:12:12' }],
+ },
+ mssql => {
+ select => "(DATEADD(dayofyear, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-17 12:12:12.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (day) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [hour => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [hour => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' hours')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' hours'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 15:12:12' }],
+ },
+ mssql => {
+ select => "(DATEADD(hour, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 15:12:12.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (hour) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [minute => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [minute => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' minutes')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' minutes'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 12:15:12' }],
+ },
+ mssql => {
+ select => "(DATEADD(minute, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 12:15:12.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (minute) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_add => [second => 3, { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [second => 3, { -ident => 'me.created_on' } ] ] ],
+ as => [ 'date' ],
sqlite => {
- stmt => "SELECT (datetime(artist.when_ended, ? || ' seconds')) FROM artist",
- bind => [[ '', 3 ]],
+ select => "(datetime(me.created_on, ? || ' seconds'))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 12:12:15' }],
+ },
+ mssql => {
+ select => "(DATEADD(second, ?, me.created_on))",
+ where => "me.id = ?",
+ bind => [['', 3], ['me.id' => 2 ]],
+ hri => [{ date => '2011-12-14 12:12:15.000' }],
+ skip => 'need working bindtypes',
},
msg => '-dt_add (second) works',
},
+
{
- func => 'select',
- args => ['artist', [ [ -dt_diff => [year => \'artist.when_started', { -ident => 'artist.when_ended' } ] ] ]],
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_add => [second => 3, { -dt_add => [ day => 1, { -ident => 'me.created_on' } ] } ] ] ],
+ as => [ 'date' ],
+ sqlite => {
+ select => "(datetime((datetime(me.created_on, ? || ' days')), ? || ' seconds'))",
+ where => "me.id = ?",
+ bind => [['', 1], [ '', 3 ], ['me.id', 2]],
+ hri => [{ date => '2011-12-15 12:12:15' }],
+ },
+ mssql => {
+ select => "(DATEADD(second, ?, (DATEADD(dayofyear, ?, me.created_on))))",
+ where => "me.id = ?",
+ bind => [['', 3], [ '', 1 ], ['me.id', 2]],
+ hri => [{ date => '2011-12-15 12:12:15.000' }],
+ skip => 'need working bindtypes',
+ },
+ msg => 'nested -dt_add works',
+ },
+
+ {
+ search => { 'me.id' => 2 },
+ select => [ [ -dt_diff => [year => \'me.starts_at', { -ident => 'me.created_on' } ] ] ],
+ as => [ 'year' ],
sqlite => {
exception_like => qr/date diff not supported for part "year" with database "SQLite"/,
},
+ mssql => {
+ select => "DATEDIFF(year, me.created_on, me.starts_at)",
+ where => "me.id = ?",
+ bind => [['me.id', 2]],
+ hri => [{ year => -1 }],
+ },
+ msg => '-dt_diff (year) works',
},
);
for my $t (@tests) {
- local $"=', ';
DB_TEST:
- for my $db (keys %sql_maker) {
- my $maker = $sql_maker{$db};
-
+ for my $db (keys %rs) {
my $db_test = $t->{$db};
next DB_TEST unless $db_test;
- my($stmt, @bind);
+ my ($r, $my_rs);
my $cref = sub {
- my $op = $t->{func};
- ($stmt, @bind) = $maker->$op (@ { $t->{args} } );
+ my $stuff = {
+ ( exists $t->{select}
+ ? ( select => $t->{select}, as => $t->{as} )
+ : ( columns => [qw(starts_at created_on skip_inflation)] )
+ )
+ };
+ $my_rs = $rs{$db}->search($t->{search}, $stuff);
+ $r = $my_rs->as_query
};
if ($db_test->{exception_like}) {
$cref->();
}
is_same_sql_bind(
- $stmt,
- \@bind,
- $db_test->{stmt},
+ $r,
+ "(SELECT $db_test->{select} FROM event me WHERE $db_test->{where})",
$db_test->{bind},
- ($t->{msg} ? $t->{msg} : ())
+ ($t->{msg} ? "$t->{msg} ($db)" : ())
);
+
+ SKIP: {
+ if (my $hri = $db_test->{hri}) {
+ skip "Cannot test database we are not connected to ($db)", 1 unless $dbs_to_test{$db};
+ skip $db_test->{skip} . " ($db)", 1 if $db_test->{skip};
+
+ my $msg = ($t->{msg} ? "$t->{msg} ($db actually pulls expected data)" : '');
+ try {
+ is_deeply [ $my_rs->hri_dump->all ], $hri, $msg;
+ } catch {
+ ok 0, $msg . " $_";
+ }
+ } }
}
}
}