File Coverage

blib/lib/Data/Model/Schema/SQL.pm
Criterion Covered Total %
statement 102 127 80.3
branch 40 62 64.5
condition 6 12 50.0
subroutine 18 19 94.7
pod 0 16 0.0
total 166 236 70.3


line stmt bran cond sub pod time code
1             package Data::Model::Schema::SQL;
2 73     73   378 use strict;
  73         136  
  73         2453  
3 73     73   364 use warnings;
  73         136  
  73         1688  
4              
5 73     73   365 use Carp ();
  73         709  
  73         160368  
6             $Carp::Internal{(__PACKAGE__)}++;
7              
8             sub new {
9 94     94 0 178 my($class, $schema) = @_;
10 94         1147 bless { schema => $schema }, $class;
11             }
12              
13             sub call_method {
14 1370     1370 0 2518 my $self = shift;
15 1370         1817 my $method = shift;
16              
17 1370 50       7594 $self->$method(@_) unless $self->{schema}->driver;
18 1370         3821 my @ret = $self->{schema}->driver->_as_sql_hook( $self, $method => @_ );
19 1370 100       3894 return @ret if defined $ret[0];
20 1159         3127 return $self->$method(@_);
21             }
22              
23             sub as_column_type {
24 179     179 0 284 my($self, $column, $args) = @_;
25 179         456 my $type = uc($args->{type});
26              
27 179   100     775 my $size = $args->{options}->{size} || 0;
28 179 50       827 $size = 0 unless $size =~ /^\d+$/;
29 179 100       1300 if ($type =~ m/int/i) {
    50          
    100          
30 7 50       23 $type .= "($size)" if $size;
31             } elsif ($type =~ m/(?:real|float|double|numeric|decimal)/i) {
32 0   0     0 my $decimals = $args->{options}->{decimals} || 0;
33 0 0       0 $decimals = 0 unless $decimals =~ /^\d+$/;
34 0 0 0     0 if ($size && $decimals) {
    0          
35 0         0 $type .= "($size,$decimals)";
36             } elsif ($size) {
37 0         0 $type .= "($size)";
38             }
39             } elsif ($type =~ m/char/i) {
40 170   100     627 $size ||= 255;
41 170         395 $type .= "($size)";;
42             }
43 179         902 $type;
44             }
45              
46             sub as_type_attributes {
47 186     186 0 305 my($self, $column, $args) = @_;
48 186         204 my $sql;
49 186 100       494 $sql .= $args->{options}->{unsigned} ? ' UNSIGNED' : '';
50 186 50       437 $sql .= $args->{options}->{zerofill} ? ' ZEROFILL' : '';
51 186 50       424 $sql .= $args->{options}->{binary} ? ' BINARY' : '';
52 186 50       389 $sql .= $args->{options}->{ascii} ? ' ASCII' : '';
53 186 50       604 $sql .= $args->{options}->{unicode} ? ' UNICODE' : '';
54 186         1103 $sql;
55             }
56              
57             sub as_default {
58 186     186 0 333 my($self, $column, $args) = @_;
59 186         343 my $default = $args->{options}->{default};
60 186 100       418 if (!defined($default)) {
61 176         1653 return '';
62             }
63 10 100 66     64 if (CORE::ref($default) and CORE::ref($default) eq 'CODE') {
64 2         17 return '';
65             }
66              
67 8 100       59 if ($args->{type} =~ m/(?:int|real|float|double|numeric|decimal|bit)/i) {
68 5         67 return ' DEFAULT ' . $default
69             }
70 3         24 return " DEFAULT '" . $default ."'";
71             }
72              
73             sub as_column {
74 186     186 0 275 my($self, $column, $args) = @_;
75              
76 186         292 my $opts = $args->{options};
77 186 50       527 return sprintf('%-15s %-15s', $column, $self->call_method( as_column_type => $column, $args ))
    100          
    50          
    50          
    50          
    50          
78             . $self->call_method( as_type_attributes => $column, $args )
79             . ($opts->{required} ? ' NOT NULL' : ($opts->{null} ? ' NULL' : ''))
80             . $self->call_method( as_default => $column, $args )
81             . ($opts->{auto_increment} ? ' AUTO_INCREMENT' : '')
82             . ($self->{unique} ? ' UNIQUE' : '')
83             . ($self->{primary_key} ? ' PRIMARY KEY' : '')
84             . ($self->{references} ? ' REFERENCES '
85             . $self->{references}->{table}->{name} .'('
86             . $self->{references}->{name} .')' : '')
87             ;
88             }
89              
90             sub as_primary_key {
91 48     48 0 90 my($self, $key) = @_;
92 48 100       77 return () unless @{ $key };
  48         554  
93 39         68 return 'PRIMARY KEY (' . join(', ', @{ $key }) .')';
  39         379  
94             }
95              
96             sub as_unique {
97 86     86 0 143 my($self, $unique) = @_;
98 86 50       169 return () unless @{ $unique };
  86         385  
99              
100 0         0 my @sql = ();
101 0         0 for my $data (@{ $unique }) {
  0         0  
102 0         0 my($name, $columns) = @{ $data };
  0         0  
103 0         0 push(@sql, 'UNIQUE ' . $name . ' (' . join(', ', @{ $columns }) . ')');
  0         0  
104             }
105 0         0 return @sql;
106             }
107              
108             sub as_foreign {
109 96     96 0 166 my $self = shift;
110 96 50       132 return () unless @{ $self->{schema}->{foreign} };
  96         508  
111              
112 0         0 my $sql = '';
113 0         0 for my $foreign (@{ $self->{schema}->{foreign} }) {
  0         0  
114 0         0 my @cols = @{ $foreign->{columns} };
  0         0  
115 0         0 my @refs = @{ $foreign->{references} };
  0         0  
116 0         0 $sql .= 'FOREIGN KEY ('
117             . join(', ', @cols)
118             . ') REFERENCES ' . $refs[0]->{table}->{name} .' ('
119             . join(', ', @refs)
120             . ')'
121             ;
122             }
123 0         0 return $sql;
124             }
125              
126             sub as_table_attributes {
127 96     96 0 148 my $self = shift;
128 96         357 my $hash = $self->{schema}->options->{create_sql_attributes};
129 96 100       340 $hash = +{} unless ref($hash) eq 'HASH';
130 96         236 my($ret) = $self->call_method( 'get_table_attributes', $hash );
131 96 50       790 $ret ? " $ret" : '';
132             }
133 0     0 0 0 sub get_table_attributes {}
134              
135             sub as_create_table {
136 96     96 0 150 my $self = shift;
137 96         243 my $schema = $self->{schema};
138              
139 96         134 my @values;
140 96         216 my %columns = %{ $schema->column };
  96         293  
141 96         410 for my $column ($schema->column_names) {
142 236         755 push @values, $self->call_method( as_column => $column, $schema->column->{$column} );
143             }
144              
145 96         191 my @key = @{ $schema->key };
  96         364  
146 96         491 my $unique_hash = $schema->unique;
147 0         0 my @unique = sort { $a->[0] cmp $b->[0] }
  10         55  
148 96         416 map { [ $_ => $unique_hash->{$_} ] }
149 96         180 keys %{ $unique_hash };
150              
151 96 100       353 if (my $name = $schema->options->{key_as_unique}) {
152 2         7 unshift @unique, [ $name, [ @key ] ];
153 2         4 @key = ();
154             }
155              
156 96         392 my $index_hash = $schema->index;
157 0         0 my @index = sort { $a->[0] cmp $b->[0] }
  22         116  
158 96         310 map { [ $_ => $index_hash->{$_} ] }
159 96         162 keys %{ $index_hash };
160              
161 96         372 push(@values, $self->call_method( 'as_primary_key', \@key ));
162 96         279 push(@values, $self->call_method( 'as_unique', \@unique ));
163 96         263 push(@values, $self->call_method( 'as_inner_index', \@index ));
164 96         243 push(@values, $self->call_method( 'as_foreign' ));
165              
166 335         892 return 'CREATE TABLE '
167             . $self->{schema}->model
168 96         364 . " (\n " . join(",\n ", grep { $_ } @values) . "\n)"
169             . $self->as_table_attributes,
170             ;
171             }
172              
173             sub as_inner_index {
174 96     96 0 209 ();
175             }
176              
177             sub as_index {
178 96     96 0 158 my $self = shift;
179 96         172 my @sql = ();
180              
181 96         149 while (my($name, $columns) = each %{ $self->{schema}->{index} }) {
  118         508  
182 22         106 push(@sql, 'CREATE'
183             . ' INDEX '
184             . $name
185             . ' ON ' . $self->{schema}->model
186 22         138 . ' (' . join(', ', @{ $columns } ) . ')'
187             );
188             }
189 96         257 return @sql;
190             }
191              
192             sub as_create_indexes {
193 96     96 0 154 my $self = shift;
194 96         230 my @ret = $self->call_method( 'as_index' );
195 96 100       758 return () unless $ret[0];
196 22         112 return @ret;
197             }
198              
199              
200             sub as_sql {
201 96     96 0 239 my $self = shift;
202 96         331 return ($self->as_create_table, $self->as_create_indexes);
203             }
204              
205              
206             1;
207              
208             __END__