File Coverage

blib/lib/DBIx/Skinny/Schema/Loader.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1             package DBIx::Skinny::Schema::Loader;
2 10     10   4194462 use strict;
  10         27  
  10         443  
3 10     10   59 use warnings;
  10         19  
  10         533  
4              
5             our $VERSION = '0.25';
6              
7 10     10   63 use Carp;
  10         25  
  10         928  
8 10     10   7636 use DBI;
  10         40014  
  10         477  
9 10     10   21489 use DBIx::Skinny::Schema;
  0            
  0            
10              
11             sub import {
12             my ($class, @args) = @_;
13             my $caller = caller;
14              
15             my @functions = qw(
16             make_schema_at
17             );
18              
19             for my $func ( @args ) {
20             if ( grep { $func } @functions ) {
21             no strict 'refs';
22             *{"$caller\::$func"} = \&$func;
23             }
24             }
25             }
26              
27             sub new {
28             my ($class) = @_;
29             bless {}, $class;
30             }
31              
32             sub supported_drivers {
33             qw(
34             SQLite
35             mysql
36             Pg
37             );
38             }
39              
40             sub connect {
41             my $self = shift;
42             return if defined $self->{ impl };
43              
44             my $opts;
45             if (@_ == 1) {
46             $opts = +{
47             dsn => $_[0]->{dsn} || '',
48             user => $_[0]->{username} || '',
49             pass => $_[0]->{password} || '',
50             connect_options => $_[0]->{connect_options} || {},
51             };
52             } else {
53             my ($dsn, $user, $pass, $connect_options) = @_;
54             $opts = {
55             dsn => $dsn || '',
56             user => $user || '',
57             pass => $pass || '',
58             connect_options => $connect_options || {},
59             };
60             }
61             $opts->{dsn} =~ /^dbi:([^:]+):/i;
62             my $driver = $1 or croak "Could not parse DSN";
63             croak "$driver is not supported by DBIx::Skinny::Schema::Loader yet"
64             unless grep { /^$driver$/ } $self->supported_drivers;
65             my $impl = __PACKAGE__ . "::DBI::$driver";
66             eval "use $impl"; ## no critic
67             die $@ if $@;
68             $self->{ impl } = $impl->new($opts);
69             }
70              
71             sub load_schema {
72             my ($class, $connect_info) = @_;
73             my $self = $class->new;
74             $connect_info ||= $class->_get_skinny_connect_info;
75             $self->connect(
76             $connect_info->{ dsn },
77             $connect_info->{ username },
78             $connect_info->{ password },
79             $connect_info->{ connect_options },
80             );
81              
82             my $schema = $class->schema_info;
83             for my $table ( @{ $self->{ impl }->tables } ) {
84             my $pk = $self->{ impl }->table_pk($table);
85             $schema->{ $table }->{ pk } = $pk if $pk;
86             $schema->{ $table }->{ columns } = $self->{ impl }->table_columns($table);
87             $schema->{ $table }->{ row_class } = DBIx::Skinny::Util::mk_row_class($class, $table);
88             }
89             return $self;
90             }
91              
92             sub _get_skinny_connect_info {
93             my $class = shift;
94             $class = ref $class || $class;
95             (my $skinny_class = $class) =~ s/::Schema//;
96             return $skinny_class->connect_info;
97             }
98              
99             sub make_schema_at {
100             my $self = (ref $_[0] eq 'DBIx::Skinny::Schema::Loader') ? shift : __PACKAGE__->new;
101             my ($schema_class, $options, $connect_info) = @_;
102              
103             $self->connect(ref $connect_info eq 'HASH' ? $connect_info : @{ $connect_info });
104              
105             my $schema = $self->_insert_header;
106             $schema .= "package $schema_class;\nuse DBIx::Skinny::Schema;\n\n";
107              
108             $schema .= $self->_insert_template($options->{ before_template });
109             $schema .= $self->_insert_template($options->{ template });
110              
111             for my $table ( @{ $self->_get_tables($options->{ ignore_rules }) } ) {
112             my $pk = $self->{ impl }->table_pk($table);
113             $schema .= $self->_make_install_table_text(
114             {
115             table => $table,
116             pk => ref $pk ? $pk : [ $pk ],
117             columns => $self->{ impl }->table_columns($table),
118             },
119             $options->{ table_template }
120             );
121             }
122              
123             $schema .= $self->_insert_template($options->{ after_template });
124              
125             $schema .= "1;";
126             return $schema;
127             }
128              
129             sub _insert_header {
130             "# THIS FILE IS AUTOGENERATED BY DBIx::Skinny::Schema::Loader $VERSION, DO NOT EDIT DIRECTLY.\n\n";
131             }
132              
133             sub _insert_template {
134             my ($self, $template) = @_;
135             return '' unless $template;
136             chomp $template;
137              
138             "# ---- beginning of custom template ----\n" .
139             $template . "\n" .
140             "# ---- end of custom template ----\n\n";
141             }
142              
143             sub _make_install_table_text {
144             my ($self, $params, $template) = @_;
145             my $table = $params->{ table };
146             my $pk = join " ", @{ $params->{ pk } };
147             my $columns = join " ", @{ $params->{ columns } };
148             unless ($template) {
149             $template = "install_table [% table %] => schema {\n";
150             $template .= " pk qw/[% pk %]/;\n" if $pk;
151             $template .= " columns qw/[% columns %]/;\n};\n\n";
152             }
153              
154             $template =~ s/\[% table %\]/$table/g;
155             $template =~ s/\[% pk %\]/$pk/g;
156             $template =~ s/\[% columns %\]/$columns/g;
157             return $template;
158             }
159              
160             sub _get_tables {
161             my ($self, $ignore_rules) = @_;
162             my @tables;
163             for my $table ( @{ $self->{ impl }->tables } ) {
164             my $ignore;
165             for my $rule ( @$ignore_rules ) {
166             $ignore++ and last if $table =~ $rule;
167             }
168             push @tables, $table unless $ignore;
169             }
170             return \@tables;
171             }
172              
173             1;
174             __END__