File Coverage

script/dbicdump
Criterion Covered Total %
statement 52 72 72.2
branch 6 18 33.3
condition 1 12 8.3
subroutine 13 13 100.0
pod n/a
total 72 115 62.6


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2              
3             =encoding UTF-8
4              
5             =head1 NAME
6              
7             dbicdump - Dump a schema using DBIx::Class::Schema::Loader
8              
9             =head1 SYNOPSIS
10              
11             dbicdump
12             dbicdump [-I ] [-o = ] \
13            
14              
15             Examples:
16              
17             $ dbicdump schema.conf
18              
19             $ dbicdump -o dump_directory=./lib \
20             -o components='["InflateColumn::DateTime"]' \
21             MyApp::Schema dbi:SQLite:./foo.db
22              
23             $ dbicdump -o dump_directory=./lib \
24             -o components='["InflateColumn::DateTime"]' \
25             MyApp::Schema dbi:SQLite:./foo.db '{ quote_char => "\"" }'
26              
27             $ dbicdump -Ilib -o dump_directory=./lib \
28             -o components='["InflateColumn::DateTime"]' \
29             -o preserve_case=1 \
30             MyApp::Schema dbi:mysql:database=foo user pass \
31             '{ quote_char => "`" }'
32              
33             $ dbicdump -o dump_directory=./lib \
34             -o components='["InflateColumn::DateTime"]' \
35             MyApp::Schema 'dbi:mysql:database=foo;host=domain.tld;port=3306' \
36             user pass
37              
38             On Windows that would be:
39              
40             $ dbicdump -o dump_directory=.\lib ^
41             -o components="[q{InflateColumn::DateTime}]" ^
42             -o preserve_case=1 ^
43             MyApp::Schema dbi:mysql:database=foo user pass ^
44             "{ quote_char => q{`} }"
45              
46             Configuration files must have schema_class and connect_info sections,
47             an example of a general config file is as follows:
48              
49             schema_class MyApp::Schema
50              
51             lib /extra/perl/libs
52              
53             # connection string
54            
55             dsn dbi:mysql:example
56             user root
57             pass secret
58            
59              
60             # dbic loader options
61            
62             dump_directory ./lib
63             components InflateColumn::DateTime
64             components TimeStamp
65            
66              
67             Using a config file requires L installed.
68              
69             The optional C key is equivalent to the C<-I> option.
70              
71             =head1 DESCRIPTION
72              
73             Dbicdump generates a L schema using
74             L and dumps it to disk.
75              
76             You can pass any L constructor option using
77             C<< -o
78             replaced with C<_> and values that look like references or quote-like
79             operators will be C-ed before being passed to the constructor.
80              
81             The C option defaults to the current directory if not
82             specified.
83              
84             =head1 SEE ALSO
85              
86             L, L.
87              
88             =head1 AUTHORS
89              
90             See L.
91              
92             =head1 LICENSE
93              
94             This program is free software; you can redistribute it and/or modify it
95             under the same terms as Perl itself.
96              
97             =cut
98              
99 34     34   199909 use strict;
  34         56  
  34         1349  
100 34     34   191 use warnings;
  34         69  
  34         1939  
101 34     34   23767 use Getopt::Long;
  34         555241  
  34         229  
102 34     34   24956 use Pod::Usage;
  34         2476282  
  34         5174  
103 34     34   21847 use DBIx::Class::Schema::Loader 'make_schema_at';
  34         199  
  34         144  
104 34     34   224 use namespace::clean;
  34         59  
  34         160  
105 34     34   44129 use DBIx::Class::Schema::Loader::Base ();
  34         184  
  34         1365  
106 34     34   317 use DBIx::Class::Schema::Loader::Optional::Dependencies ();
  34         83  
  34         35412  
107 34         8199909 require lib;
108              
109 34         37324 my $loader_options;
110              
111 34         367 Getopt::Long::Configure('gnu_getopt');
112              
113             GetOptions(
114 4     4   946 'I=s' => sub { shift; lib->import(shift) },
  4         27  
115 34         1877 'loader-option|o=s%' => \&handle_option,
116             );
117              
118 34   50     3136 $loader_options->{dump_directory} ||= '.';
119              
120 34 50       218 if (@ARGV == 1) {
121 0 0       0 if (not DBIx::Class::Schema::Loader::Optional::Dependencies->req_ok_for('dbicdump_config')) {
122 0         0 die sprintf "You must install the following CPAN modules to use a config file with dbicdump: %s.\n",
123             DBIx::Class::Schema::Loader::Optional::Dependencies->req_missing_for('dbicdump_config');
124             }
125              
126 0         0 my $configuration_file = shift @ARGV;
127              
128 0         0 my $configurations = Config::Any->load_files({
129             use_ext => 1,
130             flatten_to_hash => 1,
131             files => [$configuration_file]
132             });
133              
134 0         0 my $c = (values %$configurations)[0];
135              
136 0 0 0     0 unless (keys %{$c->{connect_info}} && $c->{schema_class}) {
  0         0  
137 0         0 pod2usage(1);
138             }
139              
140 0         0 my @libs;
141              
142 0 0       0 if ($c->{lib}) {
143 0 0       0 if (ref $c->{lib}) {
144 0         0 @libs = @{ $c->{lib} };
  0         0  
145             }
146              
147 0         0 @libs = ($c->{lib});
148             }
149              
150 0         0 lib->import($_) for @libs;
151              
152             my ($dsn, $user, $pass, $options) =
153 0         0 map { $c->{connect_info}->{$_} } qw/dsn user pass options/;
  0         0  
154 0   0     0 $options ||= {};
155             $c->{loader_options}->{dump_directory} ||=
156 0   0     0 $loader_options->{dump_directory};
157              
158             make_schema_at(
159             $c->{schema_class},
160             $c->{loader_options} || {},
161 0   0     0 [ $dsn, $user, $pass, $options ],
162             );
163             }
164             else {
165 34 50       463 my ($schema_class, @loader_connect_info) = @ARGV
166             or pod2usage(1);
167              
168 34         849 my $dsn = shift @loader_connect_info;
169              
170 34 50       393 my ($user, $pass) = $dsn =~ /sqlite/i ? ('', '')
171             : splice @loader_connect_info, 0, 2;
172              
173 34         270 my @extra_connect_info_opts = map parse_value($_), @loader_connect_info;
174              
175 34         329 make_schema_at(
176             $schema_class,
177             $loader_options,
178             [ $dsn, $user, $pass, @extra_connect_info_opts ],
179             );
180             }
181              
182 32         9770 exit 0;
183              
184             sub parse_value {
185 157     157   261 my $value = shift;
186              
187 157 100   1   2000 $value = eval $value if $value =~ /^\s*(?:sub\s*\{|q\w?\s*[^\w\s]|[[{])/;
  1     1   5  
  1         2  
  1         86  
  1         5  
  1         1  
  1         93  
188              
189 157         360 return $value;
190             }
191              
192             sub handle_option {
193 154     154   49110 my ($self, $key, $value) = @_;
194              
195 154         354 $key =~ tr/-/_/;
196 154 50       1988 die "Unknown option: $key\n"
197             unless DBIx::Class::Schema::Loader::Base->can($key);
198              
199 154         388 $value = parse_value $value;
200              
201 154         1055 $loader_options->{$key} = $value;
202             }
203              
204             1;
205              
206             __END__