Multiple code/test/doc improvements for MSSQL over DBD::ADO
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Optional / Dependencies.pm
CommitLineData
8057ed01 1package DBIx::Class::Optional::Dependencies;
2
3use warnings;
4use strict;
5
fb39747c 6use Carp;
7
8# NO EXTERNAL NON-5.8.1 CORE DEPENDENCIES EVER (e.g. C::A::G)
8057ed01 9# This module is to be loaded by Makefile.PM on a pristine system
10
f6b26571 11# POD is generated automatically by calling _gen_pod from the
12# Makefile.PL in $AUTHOR mode
13
2a2a7b23 14my $json_any = {
15 'JSON::Any' => '1.22',
16};
17
2b48ebff 18my $moose_basic = {
68de9438 19 'Moose' => '0.98',
20 'MooseX::Types' => '0.21',
21};
22
23my $replicated = {
24 %$moose_basic,
2b48ebff 25};
26
ebcd0e4f 27my $admin_basic = {
28 %$moose_basic,
2a2a7b23 29 %$json_any,
68de9438 30 'MooseX::Types::Path::Class' => '0.05',
31 'MooseX::Types::JSON' => '0.02',
68de9438 32 'namespace::autoclean' => '0.09',
33};
34
35my $datetime_basic = {
36 'DateTime' => '0.55',
37 'DateTime::Format::Strptime' => '1.2',
ebcd0e4f 38};
39
c7d50a7d 40my $id_shortener = {
41 'Math::BigInt' => '1.89',
42 'Math::Base36' => '0.07',
43};
44
be68095d 45my $rdbms_sqlite = {
46 'DBD::SQLite' => '0',
47};
48my $rdbms_pg = {
49 'DBD::Pg' => '0',
50};
51my $rdbms_mssql_odbc = {
52 'DBD::ODBC' => '0',
53};
54my $rdbms_mssql_sybase = {
55 'DBD::Sybase' => '0',
56};
56dca25f 57my $rdbms_mssql_ado = {
58 'DBD::ADO' => '0',
59};
be68095d 60my $rdbms_mysql = {
61 'DBD::mysql' => '0',
62};
63my $rdbms_oracle = {
64 'DBD::Oracle' => '0',
65 %$id_shortener,
66};
67my $rdbms_ase = {
68 'DBD::Sybase' => '0',
69};
70my $rdbms_db2 = {
71 'DBD::DB2' => '0',
72};
73
8057ed01 74my $reqs = {
75 dist => {
76 #'Module::Install::Pod::Inherit' => '0.01',
77 },
78
79 replicated => {
68de9438 80 req => $replicated,
f6b26571 81 pod => {
82 title => 'Storage::Replicated',
83 desc => 'Modules required for L<DBIx::Class::Storage::DBI::Replicated>',
84 },
8057ed01 85 },
86
68de9438 87 test_replicated => {
88 req => {
89 %$replicated,
90 'Test::Moose' => '0',
91 },
92 },
93
94
8057ed01 95 admin => {
2b48ebff 96 req => {
ebcd0e4f 97 %$admin_basic,
98 },
99 pod => {
100 title => 'DBIx::Class::Admin',
101 desc => 'Modules required for the DBIx::Class administrative library',
102 },
103 },
104
a4a02f15 105 admin_script => {
ebcd0e4f 106 req => {
2b48ebff 107 %$moose_basic,
ebcd0e4f 108 %$admin_basic,
2b48ebff 109 'Getopt::Long::Descriptive' => '0.081',
2b48ebff 110 'Text::CSV' => '1.16',
111 },
e144415f 112 pod => {
113 title => 'dbicadmin',
114 desc => 'Modules required for the CLI DBIx::Class interface dbicadmin',
115 },
8057ed01 116 },
117
118 deploy => {
f6b26571 119 req => {
9e34d554 120 'SQL::Translator' => '0.11006',
f6b26571 121 },
122 pod => {
123 title => 'Storage::DBI::deploy()',
c7d50a7d 124 desc => 'Modules required for L<DBIx::Class::Storage::DBI/deploy> and L<DBIx::Class::Storage::DBI/deployment_statements>',
f6b26571 125 },
8057ed01 126 },
127
c7d50a7d 128 id_shortener => {
129 req => $id_shortener,
130 },
131
a109c954 132 test_pod => {
f6b26571 133 req => {
14d17d71 134 'Test::Pod' => '1.41',
a109c954 135 },
136 },
137
138 test_podcoverage => {
139 req => {
f6b26571 140 'Test::Pod::Coverage' => '1.08',
141 'Pod::Coverage' => '0.20',
a109c954 142 },
143 },
144
145 test_notabs => {
146 req => {
d146b340 147 'Test::NoTabs' => '0.9',
a109c954 148 },
149 },
150
151 test_eol => {
152 req => {
d146b340 153 'Test::EOL' => '0.6',
f6b26571 154 },
8057ed01 155 },
156
2a2a7b23 157 test_prettydebug => {
158 req => $json_any,
159 },
160
226d1c35 161 test_leaks => {
f6b26571 162 req => {
f6b26571 163 'Test::Memory::Cycle' => '0',
164 'Devel::Cycle' => '1.10',
a109c954 165 },
166 },
f6b26571 167
68de9438 168 test_dt => {
169 req => $datetime_basic,
170 },
171
172 test_dt_sqlite => {
a109c954 173 req => {
68de9438 174 %$datetime_basic,
f6b26571 175 # t/36datetime.t
176 # t/60core.t
177 'DateTime::Format::SQLite' => '0',
68de9438 178 },
179 },
f6b26571 180
68de9438 181 test_dt_mysql => {
182 req => {
183 %$datetime_basic,
9c92bb1c 184 # t/inflate/datetime_mysql.t
185 # (doesn't need Mysql itself)
68de9438 186 'DateTime::Format::MySQL' => '0',
187 },
188 },
9c92bb1c 189
68de9438 190 test_dt_pg => {
191 req => {
192 %$datetime_basic,
9c92bb1c 193 # t/inflate/datetime_pg.t
194 # (doesn't need PG itself)
ab35aeab 195 'DateTime::Format::Pg' => '0.16004',
f6b26571 196 },
8057ed01 197 },
198
68de9438 199 test_cdbicompat => {
f6b26571 200 req => {
201 'DBIx::ContextualFetch' => '0',
202 'Class::DBI::Plugin::DeepAbstractSearch' => '0',
203 'Class::Trigger' => '0',
204 'Time::Piece::MySQL' => '0',
205 'Clone' => '0',
206 'Date::Simple' => '3.03',
207 },
8057ed01 208 },
209
be68095d 210 # this is just for completeness as SQLite
211 # is a core dep of DBIC for testing
212 rdbms_sqlite => {
213 req => {
214 %$rdbms_sqlite,
215 },
216 pod => {
217 title => 'SQLite support',
218 desc => 'Modules required to connect to SQLite',
219 },
220 },
221
222 rdbms_pg => {
223 req => {
224 %$rdbms_pg,
225 },
226 pod => {
227 title => 'PostgreSQL support',
228 desc => 'Modules required to connect to PostgreSQL',
229 },
230 },
231
232 rdbms_mssql_odbc => {
233 req => {
234 %$rdbms_mssql_odbc,
235 },
236 pod => {
237 title => 'MSSQL support via DBD::ODBC',
238 desc => 'Modules required to connect to MSSQL via DBD::ODBC',
239 },
240 },
241
242 rdbms_mssql_sybase => {
243 req => {
244 %$rdbms_mssql_sybase,
245 },
246 pod => {
247 title => 'MSSQL support via DBD::Sybase',
56dca25f 248 desc => 'Modules required to connect to MSSQL via DBD::Sybase',
249 },
250 },
251
252 rdbms_mssql_ado => {
253 req => {
254 %$rdbms_mssql_ado,
255 },
256 pod => {
257 title => 'MSSQL support via DBD::ADO (Windows only)',
258 desc => 'Modules required to connect to MSSQL via DBD::ADO. This particular DBD is available on Windows only',
be68095d 259 },
260 },
261
262 rdbms_mysql => {
263 req => {
264 %$rdbms_mysql,
265 },
266 pod => {
267 title => 'MySQL support',
268 desc => 'Modules required to connect to MySQL',
269 },
270 },
271
272 rdbms_oracle => {
273 req => {
274 %$rdbms_oracle,
275 },
276 pod => {
277 title => 'Oracle support',
278 desc => 'Modules required to connect to Oracle',
279 },
280 },
281
282 rdbms_ase => {
283 req => {
284 %$rdbms_ase,
285 },
286 pod => {
287 title => 'Sybase ASE support',
288 desc => 'Modules required to connect to Sybase ASE',
289 },
290 },
291
292 rdbms_db2 => {
293 req => {
294 %$rdbms_db2,
295 },
296 pod => {
297 title => 'DB2 support',
298 desc => 'Modules required to connect to DB2',
299 },
300 },
301
302# the order does matter because the rdbms support group might require
303# a different version that the test group
68de9438 304 test_rdbms_pg => {
f6b26571 305 req => {
306 $ENV{DBICTEST_PG_DSN}
307 ? (
be68095d 308 %$rdbms_pg,
f6b26571 309 'Sys::SigAction' => '0',
310 'DBD::Pg' => '2.009002',
f6b26571 311 ) : ()
312 },
8057ed01 313 },
314
afae8507 315 test_rdbms_mssql_odbc => {
316 req => {
317 $ENV{DBICTEST_MSSQL_ODBC_DSN}
318 ? (
be68095d 319 %$rdbms_mssql_odbc,
afae8507 320 ) : ()
321 },
322 },
323
56dca25f 324 test_rdbms_mssql_ado => {
325 req => {
326 $ENV{DBICTEST_MSSQL_ADO_DSN}
327 ? (
328 %$rdbms_mssql_ado,
329 ) : ()
330 },
331 },
332
afae8507 333 test_rdbms_mssql_sybase => {
334 req => {
335 $ENV{DBICTEST_MSSQL_DSN}
336 ? (
be68095d 337 %$rdbms_mssql_sybase,
afae8507 338 ) : ()
339 },
340 },
341
68de9438 342 test_rdbms_mysql => {
f6b26571 343 req => {
344 $ENV{DBICTEST_MYSQL_DSN}
345 ? (
be68095d 346 %$rdbms_mysql,
f6b26571 347 ) : ()
348 },
8057ed01 349 },
350
68de9438 351 test_rdbms_oracle => {
f6b26571 352 req => {
353 $ENV{DBICTEST_ORA_DSN}
354 ? (
be68095d 355 %$rdbms_oracle,
f6b26571 356 'DateTime::Format::Oracle' => '0',
e1b7e9b4 357 'DBD::Oracle' => '1.24',
f6b26571 358 ) : ()
359 },
8057ed01 360 },
361
68de9438 362 test_rdbms_ase => {
f6b26571 363 req => {
364 $ENV{DBICTEST_SYBASE_DSN}
365 ? (
be68095d 366 %$rdbms_ase,
367 'DateTime::Format::Sybase' => '0',
f6b26571 368 ) : ()
369 },
8057ed01 370 },
371
68de9438 372 test_rdbms_db2 => {
f58a165c 373 req => {
374 $ENV{DBICTEST_DB2_DSN}
375 ? (
be68095d 376 %$rdbms_db2,
f58a165c 377 ) : ()
378 },
379 },
380
42168332 381 test_memcached => {
382 req => {
383 $ENV{DBICTEST_MEMCACHED}
384 ? (
385 'Cache::Memcached' => 0,
386 ) : ()
387 },
388 },
389
8057ed01 390};
391
f6b26571 392
fb39747c 393sub req_list_for {
394 my ($class, $group) = @_;
395
f6b26571 396 croak "req_list_for() expects a requirement group name"
fb39747c 397 unless $group;
398
f6b26571 399 my $deps = $reqs->{$group}{req}
400 or croak "Requirement group '$group' does not exist";
fb39747c 401
402 return { %$deps };
403}
404
405
406our %req_availability_cache;
407sub req_ok_for {
408 my ($class, $group) = @_;
409
410 croak "req_ok_for() expects a requirement group name"
411 unless $group;
412
d8799bab 413 return $class->_check_deps($group)->{status};
fb39747c 414}
415
416sub req_missing_for {
417 my ($class, $group) = @_;
418
419 croak "req_missing_for() expects a requirement group name"
420 unless $group;
421
d8799bab 422 return $class->_check_deps($group)->{missing};
fb39747c 423}
424
425sub req_errorlist_for {
426 my ($class, $group) = @_;
427
428 croak "req_errorlist_for() expects a requirement group name"
429 unless $group;
430
d8799bab 431 return $class->_check_deps($group)->{errorlist};
fb39747c 432}
433
434sub _check_deps {
435 my ($class, $group) = @_;
436
d8799bab 437 return $req_availability_cache{$group} ||= do {
438
439 my $deps = $class->req_list_for ($group);
440
441 my %errors;
442 for my $mod (keys %$deps) {
443 my $req_line = "require $mod;";
444 if (my $ver = $deps->{$mod}) {
445 $req_line .= "$mod->VERSION($ver);";
446 }
447
448 eval $req_line;
449
450 $errors{$mod} = $@ if $@;
451 }
452
453 my $res;
fb39747c 454
d8799bab 455 if (keys %errors) {
456 my $missing = join (', ', map { $deps->{$_} ? "$_ >= $deps->{$_}" : $_ } (sort keys %errors) );
457 $missing .= " (see $class for details)" if $reqs->{$group}{pod};
458 $res = {
459 status => 0,
460 errorlist => \%errors,
461 missing => $missing,
462 };
fb39747c 463 }
464 else {
d8799bab 465 $res = {
466 status => 1,
467 errorlist => {},
468 missing => '',
469 };
fb39747c 470 }
471
d8799bab 472 $res;
473 };
fb39747c 474}
475
e3fc11e1 476sub req_group_list {
477 return { map { $_ => { %{ $reqs->{$_}{req} || {} } } } (keys %$reqs) };
478}
479
480# This is to be called by the author only (automatically in Makefile.PL)
f6b26571 481sub _gen_pod {
ccebe1f1 482 my ($class, $distver) = @_;
31fa1764 483
af4ac504 484 my $modfn = __PACKAGE__ . '.pm';
485 $modfn =~ s/\:\:/\//g;
f6b26571 486
31fa1764 487 my $podfn = __FILE__;
488 $podfn =~ s/\.pm$/\.pod/;
489
ccebe1f1 490 $distver ||=
31fa1764 491 eval { require DBIx::Class; DBIx::Class->VERSION; }
492 ||
ccebe1f1 493 die
31fa1764 494"\n\n---------------------------------------------------------------------\n" .
495'Unable to load core DBIx::Class module to determine current version, '.
496'possibly due to missing dependencies. Author-mode autodocumentation ' .
497"halted\n\n" . $@ .
498"\n\n---------------------------------------------------------------------\n"
31fa1764 499 ;
500
e3fc11e1 501 my $sqltver = $class->req_list_for ('deploy')->{'SQL::Translator'}
502 or die "Hrmm? No sqlt dep?";
7e3dc46f 503
f6b26571 504 my @chunks = (
d8799bab 505 <<'EOC',
af4ac504 506#########################################################################
507##################### A U T O G E N E R A T E D ########################
508#########################################################################
509#
510# The contents of this POD file are auto-generated. Any changes you make
511# will be lost. If you need to change the generated text edit _gen_pod()
512# at the end of $modfn
513#
514EOC
f6b26571 515 '=head1 NAME',
7e3dc46f 516 "$class - Optional module dependency specifications (for module authors)",
e3fc11e1 517 '=head1 SYNOPSIS',
d8799bab 518 <<"EOS",
7e3dc46f 519Somewhere in your build-file (e.g. L<Module::Install>'s Makefile.PL):
520
521 ...
522
523 configure_requires 'DBIx::Class' => '$distver';
524
525 require $class;
526
be68095d 527 my \$deploy_deps = $class->req_list_for('deploy');
7e3dc46f 528
529 for (keys %\$deploy_deps) {
530 requires \$_ => \$deploy_deps->{\$_};
531 }
532
533 ...
534
535Note that there are some caveats regarding C<configure_requires()>, more info
536can be found at L<Module::Install/configure_requires>
537EOS
f6b26571 538 '=head1 DESCRIPTION',
539 <<'EOD',
540Some of the less-frequently used features of L<DBIx::Class> have external
541module dependencies on their own. In order not to burden the average user
542with modules he will never use, these optional dependencies are not included
543in the base Makefile.PL. Instead an exception with a descriptive message is
544thrown when a specific feature is missing one or several modules required for
545its operation. This module is the central holding place for the current list
7e3dc46f 546of such dependencies, for DBIx::Class core authors, and DBIx::Class extension
547authors alike.
f6b26571 548EOD
549 '=head1 CURRENT REQUIREMENT GROUPS',
550 <<'EOD',
551Dependencies are organized in C<groups> and each group can list one or more
552required modules, with an optional minimum version (or 0 for any version).
ecb68746 553The group name can be used in the
f6b26571 554EOD
555 );
556
557 for my $group (sort keys %$reqs) {
558 my $p = $reqs->{$group}{pod}
559 or next;
560
561 my $modlist = $reqs->{$group}{req}
562 or next;
563
564 next unless keys %$modlist;
565
566 push @chunks, (
567 "=head2 $p->{title}",
568 "$p->{desc}",
569 '=over',
570 ( map { "=item * $_" . ($modlist->{$_} ? " >= $modlist->{$_}" : '') } (sort keys %$modlist) ),
571 '=back',
572 "Requirement group: B<$group>",
573 );
574 }
575
576 push @chunks, (
577 '=head1 METHODS',
e3fc11e1 578 '=head2 req_group_list',
579 '=over',
d8799bab 580 '=item Arguments: none',
e3fc11e1 581 '=item Returns: \%list_of_requirement_groups',
582 '=back',
d8799bab 583 <<'EOD',
e3fc11e1 584This method should be used by DBIx::Class packagers, to get a hashref of all
585dependencies keyed by dependency group. Each key (group name) can be supplied
586to one of the group-specific methods below.
587EOD
588
f6b26571 589 '=head2 req_list_for',
590 '=over',
591 '=item Arguments: $group_name',
592 '=item Returns: \%list_of_module_version_pairs',
593 '=back',
d8799bab 594 <<'EOD',
f6b26571 595This method should be used by DBIx::Class extension authors, to determine the
7e3dc46f 596version of modules a specific feature requires in the B<current> version of
e3fc11e1 597DBIx::Class. See the L</SYNOPSIS> for a real-world
7e3dc46f 598example.
f6b26571 599EOD
600
601 '=head2 req_ok_for',
602 '=over',
603 '=item Arguments: $group_name',
604 '=item Returns: 1|0',
605 '=back',
d8799bab 606 <<'EOD',
607Returns true or false depending on whether all modules required by
608C<$group_name> are present on the system and loadable.
609EOD
f6b26571 610
611 '=head2 req_missing_for',
612 '=over',
613 '=item Arguments: $group_name',
614 '=item Returns: $error_message_string',
615 '=back',
d8799bab 616 <<"EOD",
f6b26571 617Returns a single line string suitable for inclusion in larger error messages.
618This method would normally be used by DBIx::Class core-module author, to
619indicate to the user that he needs to install specific modules before he will
620be able to use a specific feature.
621
e3fc11e1 622For example if some of the requirements for C<deploy> are not available,
623the returned string could look like:
f6b26571 624
e3fc11e1 625 SQL::Translator >= $sqltver (see $class for details)
f6b26571 626
627The author is expected to prepend the necessary text to this message before
628returning the actual error seen by the user.
629EOD
630
631 '=head2 req_errorlist_for',
632 '=over',
633 '=item Arguments: $group_name',
634 '=item Returns: \%list_of_loaderrors_per_module',
635 '=back',
636 <<'EOD',
637Returns a hashref containing the actual errors that occured while attempting
638to load each module in the requirement group.
639EOD
fb8ae353 640 '=head1 AUTHOR',
641 'See L<DBIx::Class/CONTRIBUTORS>.',
642 '=head1 LICENSE',
643 'You may distribute this code under the same terms as Perl itself',
f6b26571 644 );
645
31fa1764 646 open (my $fh, '>', $podfn) or croak "Unable to write to $podfn: $!";
f6b26571 647 print $fh join ("\n\n", @chunks);
648 close ($fh);
649}
650
8057ed01 6511;