X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F10_02mysql_common.t;h=504e60c12e6b2e919f9f64cebfebeaae4832f6b0;hb=dbe5c90463dd1b323513739b1d27607186caddac;hp=bf6eb4a87e2f72c2362e59dd4149681cf21e313d;hpb=5c06aa08ab17d9d0e8437a990b5717238deeb8fd;p=dbsrgits%2FDBIx-Class-Schema-Loader.git diff --git a/t/10_02mysql_common.t b/t/10_02mysql_common.t index bf6eb4a..504e60c 100644 --- a/t/10_02mysql_common.t +++ b/t/10_02mysql_common.t @@ -1,33 +1,49 @@ +use DBIx::Class::Schema::Loader::Optional::Dependencies + -skip_all_without => 'test_rdbms_mysql'; + use strict; -use File::Slurp qw(slurp); +use warnings; use Test::More; +use Test::Exception; +use Try::Tiny; +use File::Path 'rmtree'; +use DBIx::Class::Schema::Loader::Utils 'slurp_file'; +use DBIx::Class::Schema::Loader 'make_schema_at'; + use lib qw(t/lib); + use dbixcsl_common_tests; -use utf8; -use Encode 'decode'; +use dbixcsl_test_dir '$tdir'; + +use constant EXTRA_DUMP_DIR => "$tdir/mysql_extra_dump"; my $dsn = $ENV{DBICTEST_MYSQL_DSN} || ''; my $user = $ENV{DBICTEST_MYSQL_USER} || ''; my $password = $ENV{DBICTEST_MYSQL_PASS} || ''; my $test_innodb = $ENV{DBICTEST_MYSQL_INNODB} || 0; -my $skip_rels_msg = 'You need to set the DBICTEST_MYSQL_INNODB environment variable to test relationships.'; +my $skip_rels_msg = 'You need to set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships.'; my $innodb = $test_innodb ? q{Engine=InnoDB} : ''; -my $tester = dbixcsl_common_tests->new( - vendor => 'Mysql', - auto_inc_pk => 'INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT', - innodb => $innodb, - dsn => $dsn, - user => $user, - password => $password, - connect_info_opts=> { on_connect_call => 'set_strict_mode' }, - loader_options => { preserve_case => 1 }, - skip_rels => $test_innodb ? 0 : $skip_rels_msg, - quote_char => '`', - no_inline_rels => 1, - no_implicit_rels => 1, +my ($schema, $databases_created); # for cleanup in END for extra tests + +diag $skip_rels_msg if not $test_innodb; + +dbixcsl_common_tests->new( + vendor => 'Mysql', + auto_inc_pk => 'INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT', + innodb => $innodb, + dsn => $dsn, + user => $user, + password => $password, + connect_info_opts => { on_connect_call => 'set_strict_mode' }, + loader_options => { preserve_case => 1 }, + skip_rels => $test_innodb ? 0 : $skip_rels_msg, + quote_char => '`', + no_inline_rels => 1, + no_implicit_rels => 1, + default_on_clause => 'RESTRICT', data_types => { # http://dev.mysql.com/doc/refman/5.5/en/data-type-overview.html # Numeric Types @@ -103,7 +119,6 @@ my $tester = dbixcsl_common_tests->new( 'time' => { data_type => 'time' }, 'year' => { data_type => 'year' }, 'year(4)' => { data_type => 'year' }, - 'year(2)' => { data_type => 'year', size => 2 }, # String Types 'char' => { data_type => 'char', size => 1 }, @@ -125,14 +140,17 @@ my $tester = dbixcsl_common_tests->new( 'longblob' => { data_type => 'longblob' }, 'longtext' => { data_type => 'longtext' }, - "enum('foo','bar','baz')" - => { data_type => 'enum', extra => { list => [qw/foo bar baz/] } }, - "enum('foo \\'bar\\' baz', 'foo ''bar'' quux')" - => { data_type => 'enum', extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } }, - "set('foo \\'bar\\' baz', 'foo ''bar'' quux')" - => { data_type => 'set', extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } }, - "set('foo','bar','baz')" - => { data_type => 'set', extra => { list => [qw/foo bar baz/] } }, + ( map { + "$_('','foo','bar','baz')" + => { data_type => $_, extra => { list => ['', qw/foo bar baz/] } }, + "$_('foo \\'bar\\' baz', 'foo ''bar'' quux')" + => { data_type => $_, extra => { list => [q{foo 'bar' baz}, q{foo 'bar' quux}] } }, + "$_('''', '''foo', 'bar''')" + => { data_type => $_, extra => { list => [qw(' 'foo bar')] } }, + "$_('\\'', '\\'foo', 'bar\\'')", + => { data_type => $_, extra => { list => [qw(' 'foo bar')] } }, + } qw(set enum) + ), # RT#68717 "enum('11,10 (<500)/0 DUN','4,90 (<120)/0 EUR') NOT NULL default '11,10 (<500)/0 DUN'" @@ -170,12 +188,27 @@ my $tester = dbixcsl_common_tests->new( PRIMARY KEY (`ISO3_code`) ) $innodb }, + # 4 through 10 are used for the multi-schema tests + qq{ + create table mysql_loader_test11 ( + id int auto_increment primary key + ) $innodb + }, + qq{ + create table mysql_loader_test12 ( + id int auto_increment primary key, + eleven_id int, + foreign key (eleven_id) references mysql_loader_test11(id) + on delete restrict on update set null + ) $innodb + }, ], pre_drop_ddl => [ 'DROP VIEW mysql_loader_test2', ], - drop => [ 'mysql_loader-test1', 'mysql_loader_test3' ], - count => 5, + drop => [ 'mysql_loader-test1', 'mysql_loader_test3', 'mysql_loader_test11', 'mysql_loader_test12' ], + count => 10 + 30 * 2, # regular + multi-schema * 2 run => sub { - my ($schema, $monikers, $classes) = @_; + my ($monikers, $classes); + ($schema, $monikers, $classes) = @_; is $monikers->{'mysql_loader-test1'}, 'MysqlLoaderTest1', 'table with dash correctly monikerized'; @@ -185,15 +218,24 @@ my $tester = dbixcsl_common_tests->new( is $rsrc->column_info('value')->{data_type}, 'varchar', 'view introspected successfully'; + # test that views are marked as such + my $view_source = $schema->resultset($monikers->{mysql_loader_test2})->result_source; + isa_ok $view_source, 'DBIx::Class::ResultSource::View', + 'view result source'; + + like $view_source->view_definition, + qr/\A \s* select \b .* \b from \s+ `.*?` \. `mysql_loader-test1` \s* \z/imsx, + 'view defintion'; + $rsrc = $schema->source('MysqlLoaderTest3'); is_deeply $rsrc->column_info('del_group')->{extra}{list}, ['19,90 (<500)/0 EUR','4,90 (<120)/0 EUR','7,90 (<200)/0 CHF','300 (<6000)/0 CZK','4,90 (<100)/0 EUR','39 (<900)/0 DKK','299 (<5000)/0 EEK','9,90 (<250)/0 EUR','3,90 (<100)/0 GBP','3000 (<70000)/0 HUF','4000 (<70000)/0 JPY','13,90 (<200)/0 LVL','99 (<2500)/0 NOK','39 (<1000)/0 PLN','1000 (<20000)/0 RUB','49 (<2500)/0 SEK','29 (<600)/0 USD','19,90 (<600)/0 EUR','0 EUR','0 CHF'], 'hairy enum introspected correctly'; my $class = $classes->{'mysql_loader-test1'}; - my $filename = $schema->_loader->get_dump_filename($class); + my $filename = $schema->loader->get_dump_filename($class); - my $code = decode('UTF-8', scalar slurp $filename); + my $code = slurp_file $filename; like $code, qr/^=head1 NAME\n\n^$class - The\nTable\n\n^=cut\n/m, 'table comment'; @@ -201,16 +243,302 @@ my $tester = dbixcsl_common_tests->new( like $code, qr/^=head2 id\n\n(.+:.+\n)+\nThe\nColumn\n\n/m, 'column comment and attrs'; + # test on delete/update fk clause introspection + ok ((my $rel_info = $schema->source('MysqlLoaderTest12')->relationship_info('eleven')), + 'got rel info'); + + is $rel_info->{attrs}{on_delete}, 'RESTRICT', + 'ON DELETE clause introspected correctly'; + + is $rel_info->{attrs}{on_update}, 'SET NULL', + 'ON UPDATE clause introspected correctly'; + + # multischema tests follow + SKIP: { + my $dbh = $schema->storage->dbh; + + try { + $dbh->do('CREATE DATABASE `dbicsl-test`'); + } + catch { + note "CREATE DATABASE returned error: '$_'"; + skip "no CREATE DATABASE privileges", 30 * 2; + }; + + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl-test`.mysql_loader_test4 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100) + ) $innodb +EOF + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl-test`.mysql_loader_test5 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + four_id INTEGER, + CONSTRAINT loader_test5_uniq UNIQUE (four_id), + FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id) + ) $innodb +EOF + + $dbh->do('CREATE DATABASE `dbicsl.test`'); + + # Test that keys are correctly cached by naming the primary and + # unique keys in this table with the same name as a table in + # the `dbicsl-test` schema differently. + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl.test`.mysql_loader_test5 ( + pk INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + four_id INTEGER, + CONSTRAINT loader_test5_uniq UNIQUE (four_id), + FOREIGN KEY (four_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id) + ) $innodb +EOF + + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl.test`.mysql_loader_test6 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + mysql_loader_test4_id INTEGER, + FOREIGN KEY (mysql_loader_test4_id) REFERENCES `dbicsl-test`.mysql_loader_test4 (id) + ) $innodb +EOF + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl.test`.mysql_loader_test7 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + six_id INTEGER UNIQUE, + FOREIGN KEY (six_id) REFERENCES `dbicsl.test`.mysql_loader_test6 (id) + ) $innodb +EOF + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl-test`.mysql_loader_test8 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + mysql_loader_test7_id INTEGER, + FOREIGN KEY (mysql_loader_test7_id) REFERENCES `dbicsl.test`.mysql_loader_test7 (id) + ) $innodb +EOF + # Test dumping a rel to a table that's not part of the dump. + $dbh->do('CREATE DATABASE `dbicsl_test_ignored`'); + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl_test_ignored`.mysql_loader_test9 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100) + ) $innodb +EOF + $dbh->do(<<"EOF"); + CREATE TABLE `dbicsl-test`.mysql_loader_test10 ( + id INT AUTO_INCREMENT PRIMARY KEY, + value VARCHAR(100), + mysql_loader_test9_id INTEGER, + FOREIGN KEY (mysql_loader_test9_id) REFERENCES `dbicsl_test_ignored`.mysql_loader_test9 (id) + ) $innodb +EOF + + $databases_created = 1; + + SKIP: foreach my $db_schema (['dbicsl-test', 'dbicsl.test'], '%') { + if ($db_schema eq '%') { + try { + $dbh->selectall_arrayref('SHOW DATABASES'); + } + catch { + skip 'no SHOW DATABASES privileges', 30; + } + } + + lives_and { + rmtree EXTRA_DUMP_DIR; + + my @warns; + local $SIG{__WARN__} = sub { + push @warns, $_[0] unless $_[0] =~ /\bcollides\b/; + }; + + make_schema_at( + 'MySQLMultiSchema', + { + naming => 'current', + db_schema => $db_schema, + dump_directory => EXTRA_DUMP_DIR, + quiet => 1, + }, + [ $dsn, $user, $password ], + ); + + diag join "\n", @warns if @warns; + + is @warns, 0; + } 'dumped schema for "dbicsl-test" and "dbicsl.test" databases with no warnings'; + + my ($test_schema, $rsrc, $rs, $row, %uniqs, $rel_info); + + lives_and { + ok $test_schema = MySQLMultiSchema->connect($dsn, $user, $password); + } 'connected test schema'; + + lives_and { + ok $rsrc = $test_schema->source('MysqlLoaderTest4'); + } 'got source for table in database name with dash'; + + is try { $rsrc->column_info('id')->{is_auto_increment} }, 1, + 'column in database name with dash'; + + is try { $rsrc->column_info('value')->{data_type} }, 'varchar', + 'column in database name with dash'; + + is try { $rsrc->column_info('value')->{size} }, 100, + 'column in database name with dash'; + + lives_and { + ok $rs = $test_schema->resultset('MysqlLoaderTest4'); + } 'got resultset for table in database name with dash'; + + lives_and { + ok $row = $rs->create({ value => 'foo' }); + } 'executed SQL on table in database name with dash'; + + SKIP: { + skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb; + + $rel_info = try { $rsrc->relationship_info('dbicsl_dash_test_mysql_loader_test5') }; + + is_deeply $rel_info->{cond}, { + 'foreign.four_id' => 'self.id' + }, 'relationship in database name with dash'; + + is $rel_info->{attrs}{accessor}, 'single', + 'relationship in database name with dash'; + + is $rel_info->{attrs}{join_type}, 'LEFT', + 'relationship in database name with dash'; + } + + lives_and { + ok $rsrc = $test_schema->source('DbicslDashTestMysqlLoaderTest5'); + } 'got source for table in database name with dash'; + + %uniqs = try { $rsrc->unique_constraints }; + + is keys %uniqs, 2, + 'got unique and primary constraint in database name with dash'; + + delete $uniqs{primary}; + + is_deeply ((values %uniqs)[0], ['four_id'], + 'unique constraint is correct in database name with dash'); + + lives_and { + ok $rsrc = $test_schema->source('MysqlLoaderTest6'); + } 'got source for table in database name with dot'; + + is try { $rsrc->column_info('id')->{is_auto_increment} }, 1, + 'column in database name with dot introspected correctly'; + + is try { $rsrc->column_info('value')->{data_type} }, 'varchar', + 'column in database name with dot introspected correctly'; + + is try { $rsrc->column_info('value')->{size} }, 100, + 'column in database name with dot introspected correctly'; + + lives_and { + ok $rs = $test_schema->resultset('MysqlLoaderTest6'); + } 'got resultset for table in database name with dot'; + + lives_and { + ok $row = $rs->create({ value => 'foo' }); + } 'executed SQL on table in database name with dot'; + + SKIP: { + skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 3 unless $test_innodb; + + $rel_info = try { $rsrc->relationship_info('mysql_loader_test7') }; + + is_deeply $rel_info->{cond}, { + 'foreign.six_id' => 'self.id' + }, 'relationship in database name with dot'; + + is $rel_info->{attrs}{accessor}, 'single', + 'relationship in database name with dot'; + + is $rel_info->{attrs}{join_type}, 'LEFT', + 'relationship in database name with dot'; + } + + lives_and { + ok $rsrc = $test_schema->source('MysqlLoaderTest7'); + } 'got source for table in database name with dot'; + + %uniqs = try { $rsrc->unique_constraints }; + + is keys %uniqs, 2, + 'got unique and primary constraint in database name with dot'; + + delete $uniqs{primary}; + + is_deeply ((values %uniqs)[0], ['six_id'], + 'unique constraint is correct in database name with dot'); + + SKIP: { + skip 'set the environment variable DBICTEST_MYSQL_INNODB=1 to test relationships', 4 unless $test_innodb; + + lives_and { + ok $test_schema->source('MysqlLoaderTest6') + ->has_relationship('mysql_loader_test4'); + } 'cross-database relationship in multi-db_schema'; + + lives_and { + ok $test_schema->source('MysqlLoaderTest4') + ->has_relationship('mysql_loader_test6s'); + } 'cross-database relationship in multi-db_schema'; + + lives_and { + ok $test_schema->source('MysqlLoaderTest8') + ->has_relationship('mysql_loader_test7'); + } 'cross-database relationship in multi-db_schema'; + + lives_and { + ok $test_schema->source('MysqlLoaderTest7') + ->has_relationship('mysql_loader_test8s'); + } 'cross-database relationship in multi-db_schema'; + } + } + } }, }, -); - -if( !$dsn || !$user ) { - $tester->skip_tests('You need to set the DBICTEST_MYSQL_DSN, DBICTEST_MYSQL_USER, and DBICTEST_MYSQL_PASS environment variables'); +)->run_tests; + +END { + if (not $ENV{SCHEMA_LOADER_TESTS_NOCLEANUP}) { + if ($databases_created && (my $dbh = try { $schema->storage->dbh })) { + foreach my $table ('`dbicsl-test`.mysql_loader_test10', + 'dbicsl_test_ignored.mysql_loader_test9', + '`dbicsl-test`.mysql_loader_test8', + '`dbicsl.test`.mysql_loader_test7', + '`dbicsl.test`.mysql_loader_test6', + '`dbicsl.test`.mysql_loader_test5', + '`dbicsl-test`.mysql_loader_test5', + '`dbicsl-test`.mysql_loader_test4') { + try { + $dbh->do("DROP TABLE $table"); + } + catch { + diag "Error dropping table: $_"; + }; + } + + foreach my $db (qw/dbicsl-test dbicsl.test dbicsl_test_ignored/) { + try { + $dbh->do("DROP DATABASE `$db`"); + } + catch { + diag "Error dropping test database $db: $_"; + }; + } + } + rmtree EXTRA_DUMP_DIR; + } } -else { - diag $skip_rels_msg if not $test_innodb; - $tester->run_tests(); -} - # vim:et sts=4 sw=4 tw=0: