Deprecate the insane forest of SQLT::Parser::DBIC arguments
[dbsrgits/DBIx-Class.git] / t / 99dbic_sqlt_parser.t
1 use strict;
2 use warnings;
3
4 use Test::More;
5 use Test::Warn;
6 use Test::Exception;
7 use Scalar::Util ();
8
9 use lib qw(t/lib);
10 use DBICTest;
11
12 BEGIN {
13   require DBIx::Class;
14   plan skip_all =>
15       'Test needs ' . DBIx::Class::Optional::Dependencies->req_missing_for ('deploy')
16     unless DBIx::Class::Optional::Dependencies->req_ok_for ('deploy')
17 }
18
19 # Test for SQLT-related leaks
20 {
21   my $s = DBICTest::Schema->clone;
22
23   my @schemas = (
24     create_schema ({ schema => $s }),
25     create_schema ({ args => { parser_args => { dbic_schema => $s } } }),
26   );
27
28   for my $parser_args_key (qw(
29     DBIx::Class::Schema
30     DBIx::Schema
31     package
32   )) {
33     warnings_exist {
34       push @schemas, create_schema({
35         args => { parser_args => { $parser_args_key => $s } }
36       });
37     } qr/\Qparser_args => {\E.+?is deprecated/,
38     "deprecated crazy parser_arg '$parser_args_key' warned";
39   }
40
41   Scalar::Util::weaken ($s);
42
43   ok (!$s, 'Schema not leaked');
44
45   isa_ok ($_, 'SQL::Translator::Schema', "SQLT schema object $_ produced")
46     for @schemas;
47 }
48
49 # make sure classname-style works
50 lives_ok { isa_ok (create_schema ({ schema => 'DBICTest::Schema' }), 'SQL::Translator::Schema', 'SQLT schema object produced') };
51
52
53 my $schema = DBICTest->init_schema( no_deploy => 1 );
54
55 # Dummy was yanked out by the sqlt hook test
56 # CustomSql tests the horrific/deprecated ->name(\$sql) hack
57 # YearXXXXCDs are views
58 #
59 my @sources = grep
60   { $_ !~ /^ (?: Dummy | CustomSql | Year\d{4}CDs ) $/x }
61   $schema->sources
62 ;
63
64 my $idx_exceptions = {
65     'Artwork'       => -1,
66     'ForceForeign'  => -1,
67     'LinerNotes'    => -1,
68     'TwoKeys'       => -1, # TwoKeys has the index turned off on the rel def
69 };
70
71 {
72   my $sqlt_schema = create_schema({ schema => $schema, args => { parser_args => { } } });
73
74   foreach my $source_name (@sources) {
75     my $table = get_table($sqlt_schema, $schema, $source_name);
76
77     my $fk_count = scalar(grep { $_->type eq 'FOREIGN KEY' } $table->get_constraints);
78     $fk_count += $idx_exceptions->{$source_name} || 0;
79     my @indices = $table->get_indices;
80
81     my $index_count = scalar(@indices);
82     is($index_count, $fk_count, "correct number of indices for $source_name with no args");
83
84     for my $index (@indices) {
85         my $source = $schema->source($source_name);
86         my $pk_test = join("\x00", $source->primary_columns);
87         my $idx_test = join("\x00", $index->fields);
88         isnt ( $pk_test, $idx_test, "no additional index for the primary columns exists in $source_name");
89     }
90   }
91 }
92
93 {
94   my $sqlt_schema = create_schema({ schema => $schema, args => { parser_args => { add_fk_index => 1 } } });
95
96   foreach my $source_name (@sources) {
97     my $table = get_table($sqlt_schema, $schema, $source_name);
98
99     my $fk_count = scalar(grep { $_->type eq 'FOREIGN KEY' } $table->get_constraints);
100     $fk_count += $idx_exceptions->{$source_name} || 0;
101     my @indices = $table->get_indices;
102     my $index_count = scalar(@indices);
103     is($index_count, $fk_count, "correct number of indices for $source_name with add_fk_index => 1");
104   }
105 }
106
107 {
108   my $sqlt_schema = create_schema({ schema => $schema, args => { parser_args => { add_fk_index => 0 } } });
109
110   foreach my $source (@sources) {
111     my $table = get_table($sqlt_schema, $schema, $source);
112
113     my @indices = $table->get_indices;
114     my $index_count = scalar(@indices);
115     is($index_count, 0, "correct number of indices for $source with add_fk_index => 0");
116   }
117 }
118
119 {
120     {
121         package # hide from PAUSE
122             DBICTest::Schema::NoViewDefinition;
123
124         use base qw/DBICTest::BaseResult/;
125
126         __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
127         __PACKAGE__->table('noviewdefinition');
128
129         1;
130     }
131
132     my $schema_invalid_view = $schema->clone;
133     $schema_invalid_view->register_class('NoViewDefinition', 'DBICTest::Schema::NoViewDefinition');
134
135     throws_ok { create_schema({ schema => $schema_invalid_view }) }
136         qr/view noviewdefinition is missing a view_definition/,
137         'parser detects views with a view_definition';
138 }
139
140 lives_ok (sub {
141   my $sqlt_schema = create_schema ({
142     schema => $schema,
143     args => {
144       parser_args => {
145         sources => ['CD']
146       },
147     },
148   });
149
150   is_deeply (
151     [$sqlt_schema->get_tables ],
152     ['cd'],
153     'sources limitng with relationships works',
154   );
155
156 });
157
158 {
159   package DBICTest::PartialSchema;
160
161   use base qw/DBIx::Class::Schema/;
162
163   __PACKAGE__->load_classes(
164     { 'DBICTest::Schema' => [qw/
165       CD
166       Track
167       Tag
168       Producer
169       CD_to_Producer
170     /]}
171   );
172 }
173
174 {
175   my $partial_schema = DBICTest::PartialSchema->connect(DBICTest->_database);
176
177   lives_ok (sub {
178     my $sqlt_schema = do {
179
180       local $SIG{__WARN__} = sub {
181         warn @_
182           unless $_[0] =~ /Ignoring relationship .+ related resultsource .+ is not registered with this schema/
183       };
184
185       create_schema({ schema => $partial_schema });
186     };
187
188     my @tables = $sqlt_schema->get_tables;
189
190     is_deeply (
191       [sort map { $_->name } @tables],
192       [qw/cd cd_to_producer producer tags track/],
193       'partial dbic schema parsing ok',
194     );
195
196     # the primary key is currently unnamed in sqlt - adding below
197     my %constraints_for_table = (
198       producer =>       [qw/prod_name                                                         /],
199       tags =>           [qw/tagid_cd tagid_cd_tag tags_fk_cd tags_tagid_tag tags_tagid_tag_cd /],
200       track =>          [qw/track_cd_position track_cd_title track_fk_cd                      /],
201       cd =>             [qw/cd_artist_title cd_fk_single_track                                /],
202       cd_to_producer => [qw/cd_to_producer_fk_cd cd_to_producer_fk_producer                   /],
203     );
204
205     for my $table (@tables) {
206       my $tablename = $table->name;
207       my @constraints = $table->get_constraints;
208       is_deeply (
209         [ sort map { $_->name } @constraints ],
210
211         # the primary key (present on all loaded tables) is currently named '' in sqlt
212         # subject to future changes
213         [ '', @{$constraints_for_table{$tablename}} ],
214
215         "constraints of table '$tablename' ok",
216       );
217     }
218   }, 'partial schema tests successful');
219 }
220
221 done_testing;
222
223 sub create_schema {
224   my $args = shift;
225
226   my $additional_sqltargs = $args->{args} || {};
227
228   my $sqltargs = {
229     add_drop_table => 1,
230     ignore_constraint_names => 1,
231     ignore_index_names => 1,
232     %{$additional_sqltargs}
233   };
234
235   my $sqlt = SQL::Translator->new( $sqltargs );
236
237   $sqlt->parser('SQL::Translator::Parser::DBIx::Class');
238   return $sqlt->translate(
239     $args->{schema} ? ( data => $args->{schema} ) : ()
240   ) || die $sqlt->error;
241 }
242
243 sub get_table {
244     my ($sqlt_schema, $schema, $source) = @_;
245
246     my $table_name = $schema->source($source)->from;
247     $table_name    = $$table_name if ref $table_name;
248
249     return $sqlt_schema->get_table($table_name);
250 }