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