#!/usr/bin/perl use strict; use Test::More; use DBI; # use warnings; # use Data::Dumper; ############################ ## get DB connection info ## ############################ use lib 'testconfig'; my $Config; eval q[ use DBIx::TableReferences::MSSQL::TestConfig; $Config = DBIx::TableReferences::MSSQL::TestConfig->Config; ]; ################### ## DB connection ## ################### if ($Config->{server} =~ /^skip$/i) { plan skip_all => "User has skipped the test suite. Run `perl Makefile.PL " . "-s` to reconfigure the connection parameters for the " . "test database."; } my $dbh = eval { my $dsn = join ';',map {"$_=$Config->{$_}"} qw/Server database uid pwd/; $dsn = "dbi:ODBC:driver=\{SQL Server\};$dsn;"; DBI->connect( $dsn ) }; if (not $dbh) { plan skip_all => "Couldn't connect to the database for testing. Run `perl " . "Makefile.PL -s` to reconfigure the connection parameters " . "for the test database."; } else { plan tests => 31; diag "Starting test suite. Run `perl Makefile.PL -s` to reconfigure " . "connection parameters for the test database."; } diag "Dropping tables if they exist"; for (qw/DBIx_TR_TEMP_FKTABLE DBIx_TR_TEMP_FKTABLE1 DBIx_TR_TEMP_FKTABLE2 DBIx_TR_TEMP_FKTABLE3 DBIx_TR_TEMP_FKTABLE4 DBIx_TR_TEMP_PKTABLE DBIx_TR_TEMP_PKTABLE1/) { $dbh->do( qq{ IF EXISTS ( select 1 from sysobjects where name = '$_' and uid = user_id('dbo')) DROP TABLE [dbo].[$_] } ); } diag "Creating tables and referential constraints"; $dbh->do($_) for (split /;/, <<"END_OF_SQL"); create table [dbo].[DBIx_TR_TEMP_PKTABLE] ( id int PRIMARY KEY, name varchar(50) not null ); create table [dbo].[DBIx_TR_TEMP_FKTABLE] ( id int PRIMARY KEY, pid int NOT NULL ); ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE] ADD CONSTRAINT [fk_fktable] FOREIGN KEY ([pid]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]); create table [dbo].[DBIx_TR_TEMP_PKTABLE1] ( id1 int NOT NULL, id2 int NOT NULL, name varchar(50) not null ); ALTER TABLE [dbo].[DBIx_TR_TEMP_PKTABLE1] ADD CONSTRAINT [pk_table1] PRIMARY KEY ([id1],[id2]) create table [dbo].[DBIx_TR_TEMP_FKTABLE1] ( id int PRIMARY KEY, pid1 int NOT NULL, pid2 int NOT NULL ); create table [dbo].[DBIx_TR_TEMP_FKTABLE2] ( id int PRIMARY KEY ); ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE1] ADD CONSTRAINT [fk_fktable1] FOREIGN KEY ([pid1],[pid2]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE1] ([id1],[id2]); ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE2] ADD CONSTRAINT [fk_fktable2_casc_del] FOREIGN KEY ([id]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]) ON DELETE CASCADE; ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE2] ADD CONSTRAINT [fk_fktable2_casc_upd] FOREIGN KEY ([id]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]) ON UPDATE CASCADE; ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE2] ADD CONSTRAINT [fk_fktable2_nfr] FOREIGN KEY ([id]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]) NOT FOR REPLICATION; create table [dbo].[DBIx_TR_TEMP_FKTABLE3] ( id int PRIMARY KEY ); ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE3] ADD CONSTRAINT [fk_fktable3_casc_del_nfr] FOREIGN KEY ([id]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]) ON DELETE CASCADE NOT FOR REPLICATION; create table [dbo].[DBIx_TR_TEMP_FKTABLE4] ( id int PRIMARY KEY ); ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE4] ADD CONSTRAINT [fk_fktable4_casc_upd_nfr] FOREIGN KEY ([id]) REFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] ([id]) ON UPDATE CASCADE NOT FOR REPLICATION; END_OF_SQL #################### ## initialization ## #################### diag "Running tests"; use lib 'lib'; use_ok('DBIx::TableReferences::MSSQL'); my $tr = DBIx::TableReferences::MSSQL->new( $dbh ); ok( $tr->isa('DBIx::TableReferences::MSSQL') , 'ISA is as expected'); my @tables = $tr->reftables('DBIx_TR_TEMP_FKTABLE'); ok( @tables == 1, 'FKTABLE has 1 reference'); ok("@tables" eq "dbo.DBIx_TR_TEMP_PKTABLE", "FKTABLE references PKTABLE"); @tables = $tr->reftables('DBIx_TR_TEMP_FKTABLE1'); ok( @tables == 1, 'FKTABLE1 has 1 reference'); ok("@tables" eq "dbo.DBIx_TR_TEMP_PKTABLE1", "FKTABLE1 references PKTABLE1"); @tables = $tr->reftables('DBIx_TR_TEMP_PKTABLE'); ok( @tables == 0, 'PKTABLE has 0 references'); @tables = $tr->reftables('DBIx_TR_TEMP_PKTABLE1'); ok( @tables == 0, 'PKTABLE1 has 0 references'); my $refs = $tr->references('DBIx_TR_TEMP_FKTABLE'); ok ($refs->[0]->{table} eq 'DBIx_TR_TEMP_FKTABLE', 'Table name'); ok ($refs->[0]->{owner} eq 'dbo', 'Table owner'); ok ("@{$refs->[0]->{cols}}" eq 'pid', 'Columns'); ok ($refs->[0]->{reftable} eq 'DBIx_TR_TEMP_PKTABLE', 'Referenced table name'); ok ($refs->[0]->{refowner} eq 'dbo', 'Referenced table owner'); ok ("@{$refs->[0]->{refcols}}" eq 'id', 'Referenced table columns'); ok ($refs->[0]->{sql_add} eq qq{ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE]\nADD CONSTRAINT [fk_fktable] FOREIGN KEY (\n\t[pid]\n)\nREFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE] (\n\t[id]\n)}, 'SQL Add'); ok ($refs->[0]->{sql_drop} eq qq{ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE] DROP CONSTRAINT [fk_fktable]}, 'SQL Drop'); $refs = $tr->references('dbo.DBIX_TR_TEMP_FKTABLE1'); ok ($refs->[0]->{table} eq 'DBIx_TR_TEMP_FKTABLE1', 'Table name'); ok ($refs->[0]->{owner} eq 'dbo', 'Table owner'); ok ("@{$refs->[0]->{cols}}" eq 'pid1 pid2', 'Columns'); ok ($refs->[0]->{reftable} eq 'DBIx_TR_TEMP_PKTABLE1', 'Referenced table name'); ok ($refs->[0]->{refowner} eq 'dbo', 'Referenced table owner'); ok ("@{$refs->[0]->{refcols}}" eq 'id1 id2', 'Referenced table columns'); ok ($refs->[0]->{sql_add} eq qq{ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE1]\nADD CONSTRAINT [fk_fktable1] FOREIGN KEY (\n\t[pid1],[pid2]\n)\nREFERENCES [dbo].[DBIx_TR_TEMP_PKTABLE1] (\n\t[id1],[id2]\n)}, 'SQL Add'); ok ($refs->[0]->{sql_drop} eq qq{ALTER TABLE [dbo].[DBIx_TR_TEMP_FKTABLE1] DROP CONSTRAINT [fk_fktable1]}, 'SQL Drop'); ok ($refs->[0]->{constraint} eq 'fk_fktable1', 'Constraint name'); $refs = $tr->references('dbo.DBIx_TR_TEMP_FKTABLE2'); ok (@{$refs} == 3, 'Reference count'); for (@{$refs}) { my $sql = 'FAIL UNLESS WE ENCOUNTER AN EXPECTED FK'; if ($_->{constraint} eq 'fk_fktable2_casc_del') { $sql = 'ON DELETE CASCADE'; } elsif ($_->{constraint} eq 'fk_fktable2_casc_upd') { $sql = 'ON UPDATE CASCADE'; } elsif ($_->{constraint} eq 'fk_fktable2_nfr') { $sql = 'NOT FOR REPLICATION'; } ok ($_->{sql_add} =~ /$sql$/, $sql); } $refs = $tr->references('dbo.DBIx_TR_TEMP_FKTABLE3'); ok ($refs->[0]->{sql_add} =~ /ON DELETE CASCADE NOT FOR REPLICATION$/, 'ON DELETE CASCADE NOT FOR REPLICATION'); $refs = $tr->references('dbo.DBIx_TR_TEMP_FKTABLE4'); ok ($refs->[0]->{sql_add} =~ /ON UPDATE CASCADE NOT FOR REPLICATION$/, 'ON UPDATE CASCADE NOT FOR REPLICATION'); ############# ## cleanup ## ############# END { exit; if ($dbh and $dbh->{Active}) { diag "Dropping tables"; $dbh->do($_) for (split /\s*;\s*/, <<' END_OF_SQL'); drop table dbo.DBIx_TR_TEMP_FKTABLE2; drop table dbo.DBIx_TR_TEMP_FKTABLE1; drop table dbo.DBIx_TR_TEMP_FKTABLE; drop table dbo.DBIx_TR_TEMP_PKTABLE1; drop table dbo.DBIx_TR_TEMP_PKTABLE; END_OF_SQL diag "Disconnecting from database"; $dbh->disconnect; } }