File Coverage

lib/CellBIS/SQL/Abstract/Table.pm
Criterion Covered Total %
statement 223 262 85.1
branch 73 122 59.8
condition 12 35 34.2
subroutine 11 12 91.6
pod 0 7 0.0
total 319 438 72.8


line stmt bran cond sub pod time code
1             package # hide from PAUSE
2             CellBIS::SQL::Abstract::Table;
3 10     10   58 use Mojo::Base -base;
  10         19  
  10         53  
4              
5 10     10   1270 use Scalar::Util qw(blessed);
  10         22  
  10         398  
6 10     10   46 use Mojo::Util qw(trim);
  10         18  
  10         307  
7 10     10   4018 use Hash::MultiValue;
  10         16510  
  10         22014  
8              
9             has 'db_type' => 'mysql';
10              
11             # For Foreign Key Validator:
12             # ------------------------------------------------------------------------
13             sub fk_validator {
14 2     2 0 5 my ($table_attr, $col_attr) = @_;
15 2         9 my %fk_attr = (
16             name => 0,
17             col_name => 0,
18             table_target => 0,
19             col_target => 0,
20             );
21            
22 2         12 my $fk = $table_attr->{fk};
23 2 50 33     13 if (exists $fk->{name} && $fk->{name} ne '') {
24 2         6 $fk_attr{name} = 1;
25             }
26 2 50 33     12 if (exists $fk->{col_name} && $fk->{col_name} ne '') {
27 2         5 $fk_attr{col_name} = 1;
28             }
29            
30 2 50 33     10 if (exists $fk->{table_target} && $fk->{table_target} ne '') {
31 2         4 $fk_attr{table_target} = 1;
32             }
33            
34 2 50 33     13 if (exists $fk->{col_target} && $fk->{col_target} ne '') {
35 2         5 $fk_attr{col_target} = 1;
36             }
37 2         6 my @r_val = grep {!$_} values %fk_attr;
  8         15  
38 2         4 my $size_result = scalar @r_val;
39            
40 2 50       7 if ($size_result >= 1) {
41 0         0 my $new_TableAttr = Hash::MultiValue->new(%{$table_attr});
  0         0  
42 0         0 $new_TableAttr->remove('fk');
43 0         0 $table_attr = $new_TableAttr->as_hashref;
44             }
45             else {
46 2 50       10 unless (exists $col_attr->{$fk->{col_name}}) {
47 0         0 my $new_TableAttr = Hash::MultiValue->new(%{$table_attr});
  0         0  
48 0         0 $new_TableAttr->remove('fk');
49 0         0 $table_attr = $new_TableAttr->as_hashref;
50             }
51             }
52 2         5 return $table_attr;
53             }
54              
55             # For Foreign key attribute :
56             # ------------------------------------------------------------------------
57             sub fk_attr_validator {
58 2     2 0 6 my ($fk_table) = @_;
59 2         3 my $data = '';
60 2         11 my %ondelup = (
61             'cascade' => 'CASCADE',
62             'null' => 'SET NULL',
63             'default' => 'SET DEFAULT'
64             );
65 2         32 my $ondel = 0;
66 2 50       29 if (exists $fk_table->{ondelete}) {
67 2 50       35 if (exists $ondelup{(lc $fk_table->{ondelete})}) {
68 2         4 $ondel = 1;
69 2         8 $data .= 'ON DELETE ' . $ondelup{(lc $fk_table->{ondelete})};
70             }
71             }
72            
73 2 50       6 if (exists $fk_table->{onupdate}) {
74 2 50       6 if (exists $ondelup{(lc $fk_table->{onupdate})}) {
75 2 50       6 $data .= ' ' if $ondel == 1;
76 2         7 $data .= 'ON UPDATE ' . $ondelup{(lc $fk_table->{onupdate})};
77             }
78             }
79 2         9 $data = trim($data);
80 2         29 return $data;
81             }
82              
83             # For Table Attribute Validator :
84             # ------------------------------------------------------------------------
85             sub table_attr_val {
86 4     4 0 8 my $self = shift;
87 4         12 my ($col_attr, $table_attr) = @_;
88 4         8 my $new_tblAttr = {};
89 4         8 my $attrib_table = '';
90 4   50     15 my $db_type = $self->db_type // 'mysql';
91            
92 4 100       37 if (exists $table_attr->{fk}) {
93 2         7 $table_attr = fk_validator($table_attr, $col_attr);
94 2         16 my $table_fk = '';
95 2 50       7 if (exists $table_attr->{fk}) {
96 2         5 my $fk_table = $table_attr->{fk};
97 2         4 my $fk_name = $fk_table->{name};
98 2         4 my $col_name = $fk_table->{col_name};
99 2         16 my $table_target = $fk_table->{table_target};
100 2         5 my $col_target = $fk_table->{col_target};
101 2         5 my $fk_attr = '';
102 2 50       6 if ($fk_table->{attr}) {
103 2         6 $fk_attr = fk_attr_validator($fk_table->{attr});
104             }
105 2 100       7 if ($db_type eq 'sqlite') {
106 1         3 $table_fk .= "\tCONSTRAINT $fk_name ";
107 1         3 $table_fk .= "FOREIGN KEY ($col_name) ";
108 1 50       3 $table_fk .= "REFERENCES $table_target ($col_target)\n" if $fk_attr eq '';
109 1 50       5 $table_fk .= "REFERENCES $table_target ($col_target) \n\t$fk_attr\n" unless $fk_attr eq '';
110             } else {
111 1         5 $table_fk .= "\tKEY " . $fk_name . " ($col_name), \n";
112 1         3 $table_fk .= "\tCONSTRAINT $fk_name ";
113 1         3 $table_fk .= "FOREIGN KEY ($col_name) ";
114 1 50       3 $table_fk .= "REFERENCES $table_target ($col_target)\n" if $fk_attr eq '';
115 1 50       5 $table_fk .= "REFERENCES $table_target ($col_target) \n\t$fk_attr\n" unless $fk_attr eq '';
116             }
117            
118 2         3 my $new_attrTbl = Hash::MultiValue->new(%{$table_attr});
  2         9  
119 2         72 $new_attrTbl->set(fk => $table_fk);
120 2         41 $table_attr = $new_attrTbl->as_hashref;
121             }
122             }
123 4 50       45 if (exists $table_attr->{index}) {
124 0 0 0     0 if (ref($table_attr->{index}) eq "ARRAY" and (scalar @{$table_attr->{index}}) > 0) {
  0         0  
125 0         0 my $table_index = join ',', @{$table_attr->{index}};
  0         0  
126 0         0 $table_index = 'INDEX (' . $table_index . ')';
127 0         0 my $new_attrTbl = Hash::MultiValue->new(%{$table_attr});
  0         0  
128 0         0 $new_attrTbl->set(index => $table_index);
129 0         0 $table_attr = $new_attrTbl->as_hashref;
130             }
131             }
132 4         10 my $engine = 0;
133 4 100       25 if (exists $table_attr->{engine}) {
134 2         5 $engine = 1;
135 2         21 my $r_engine = $self->_check_engine($table_attr->{engine});
136 2         8 $attrib_table .= 'ENGINE=' . $r_engine;
137             }
138 4 100       15 $attrib_table .= ' ' if ($engine == 1);
139             $attrib_table .= exists $table_attr->{charset} ?
140 4 100       18 'DEFAULT CHARSET=' . $table_attr->{charset} : 'DEFAULT CHARSET=utf8';
141 4         6 $new_tblAttr = Hash::MultiValue->new(%{$table_attr});
  4         17  
142 4         129 $new_tblAttr->set(attr => $attrib_table);
143 4         87 $table_attr = $new_tblAttr->as_hashref;
144            
145 4         50 return $table_attr;
146             }
147              
148             # For Column Attribute validator :
149             # ------------------------------------------------------------------------
150             sub table_col_attr_val {
151 4     4 0 6 my $self = shift;
152 4         11 my ($col_list, $col_attr) = @_;
153            
154 4 50       16 if (ref($col_attr) eq "HASH") {
155 4         7 my $i = 0;
156 4         7 my $until = scalar @{$col_list};
  4         8  
157 4         9 my @pk_list = ();
158 4         7 my @ai_list = ();
159 4         8 my $size_pk = 0;
160 4         7 my $size_ai = 0;
161 4         8 my $col_name = '';
162 4         6 my $curr_colAttr = {};
163 4         6 my $new_colAttr = Hash::MultiValue->new(%{$col_attr});
  4         34  
164 4         241 while ($i < $until) {
165 14         28 $col_name = $col_attr->{$col_list->[$i]};
166 14 100       30 if (exists $col_name->{'is_autoincre'}) {
167 4         7 $size_ai = ($size_ai + 1);
168 4         10 push @ai_list, $col_list->[$i];
169 4         8 $curr_colAttr = Hash::MultiValue->new(%{$col_name});
  4         17  
170 4         146 $curr_colAttr->remove('is_autoincre');
171            
172 4         192 $new_colAttr->set($col_list->[$i] => $curr_colAttr->as_hashref);
173             }
174 14         131 $i++;
175             }
176 4         13 $col_attr = $new_colAttr->as_hashref;
177            
178 4         29 $i = 0;
179 4         13 while ($i < $until) {
180 14         24 $col_name = $col_attr->{$col_list->[$i]};
181 14 100       26 if (exists $col_name->{'is_primarykey'}) {
182 4         9 $size_pk = ($size_pk + 1);
183 4         8 push @pk_list, $col_list->[$i];
184 4         8 $curr_colAttr = Hash::MultiValue->new(%{$col_name});
  4         14  
185 4         172 $curr_colAttr->remove('is_primarykey');
186            
187 4         115 $new_colAttr->set($col_list->[$i] => $curr_colAttr->as_hashref);
188             }
189 14         113 $i++;
190             }
191            
192 4 50       14 if ($size_pk >= 1) {
193 4         10 my $r_colAttr = $new_colAttr->as_hashref;
194 4         28 my $pk_table = $r_colAttr->{$pk_list[0]};
195            
196 4         8 $curr_colAttr = Hash::MultiValue->new(%{$pk_table});
  4         11  
197 4         140 $curr_colAttr->set('is_primarykey' => 1);
198            
199 4         81 $col_attr = Hash::MultiValue->new(%{$r_colAttr});
  4         15  
200 4         168 $col_attr->set($pk_list[0] => $curr_colAttr->as_hashref);
201 4         101 $col_attr = $col_attr->as_hashref;
202             }
203            
204 4 50       60 if ($size_ai >= 1) {
205 4         9 my $pk_table = $col_attr->{$pk_list[0]};
206            
207 4         7 $curr_colAttr = Hash::MultiValue->new(%{$pk_table});
  4         10  
208 4         157 $curr_colAttr->set('is_autoincre' => 1);
209            
210 4         115 $col_attr = Hash::MultiValue->new(%{$col_attr});
  4         16  
211 4         148 $col_attr->set($pk_list[0] => $curr_colAttr->as_hashref);
212 4         99 $col_attr = $col_attr->as_hashref;
213             }
214            
215 4         50 $i = 0;
216 4         13 $new_colAttr = Hash::MultiValue->new();
217 4         120 while ($i < $until) {
218 14         28 $col_name = $col_attr->{$col_list->[$i]};
219            
220 14         60 $new_colAttr->add($col_list->[$i] => $col_name);
221 14         338 $i++;
222             }
223 4         11 $col_attr = $new_colAttr->as_hashref;
224             }
225 4         111 return $col_attr;
226             }
227              
228             # For Default field table :
229             # ------------------------------------------------------------------------
230             sub default_field_tbl_val {
231 0     0 0 0 my ($type, $attr) = @_;
232 0         0 my $data = '';
233 0 0       0 if ($type eq 'datetime') {
234 0 0       0 if ($attr == 1) {
235 0         0 $data = "CURRENT_TIMESTAMP";
236             }
237 0 0       0 if ($attr eq 'yes') {
238 0         0 $data = "CURRENT_TIMESTAMP";
239             }
240             }
241 0         0 return $data;
242             }
243              
244             # For Create Column Attr :
245             # ------------------------------------------------------------------------
246             sub create_colAttr {
247 14     14 0 63 my $self = shift;
248 14         29 my ($col_name, $attr, $db_type) = @_;
249 14         26 my $data = $col_name . ' ';
250            
251 14 50       37 if (exists $attr->{type}) {
252 14 100       36 if ($db_type eq 'sqlite') {
253 7 50       24 $data .= exists $attr->{type}->{name} ? (uc $attr->{type}->{name}) . ' ' : 'varchar ';
254             } else {
255 7 50       22 $data .= exists $attr->{type}->{name} ? (uc $attr->{type}->{name}) : 'varchar';
256 7 50       23 $data .= exists $attr->{type}->{size} ? '(' . $attr->{type}->{size} . ') ' : ' ';
257             }
258             }
259            
260 14 50       33 unless (exists $attr->{custom}) {
261 14 50 33     50 if (exists $attr->{default} and $attr->{default} ne '') {
262 0 0 0     0 if (exists $attr->{onupdate} and $attr->{onupdate} ne '') {
263 0         0 my $field_default_val = default_field_tbl_val($attr->{type}->{name}, $attr->{onupdate});
264 0         0 $data .= "ON UPDATE $field_default_val ";
265             }
266             else {
267 0         0 $data .= "DEFAULT $attr->{default} ";
268             }
269             }
270            
271 14 50 33     42 if (exists $attr->{onupdate} and $attr->{onupdate} ne '') {
272 0         0 my $field_default_val = default_field_tbl_val($attr->{type}->{name}, $attr->{onupdate});
273 0         0 $data .= "ON UPDATE $field_default_val ";
274             }
275            
276 14 100       27 if (exists $attr->{is_null}) {
277 10 50       26 $data .= 'NOT NULL ' unless $attr->{is_null};
278 10 50       22 $data .= 'NULL ' if $attr->{is_null} == 1;
279             }
280             else {
281 4         23 $data .= 'NOT NULL ';
282             }
283            
284 14 100 66     44 if (exists $attr->{is_primarykey} and $attr->{is_primarykey} == 1) {
285 4         28 $data .= 'PRIMARY KEY ';
286             }
287            
288 14 100 66     39 if (exists $attr->{is_autoincre} and $attr->{is_autoincre} == 1) {
289 4 100       16 if ($db_type eq 'sqlite') {
290 2         5 $data .= 'AUTOINCREMENT ';
291             }
292             else {
293 2         5 $data .= 'AUTO_INCREMENT ';
294             }
295             }
296             }
297 14         37 $data = trim($data);
298 14         160 $data = "\t$data";
299 14         48 return $data;
300             }
301              
302             # For create query table :
303             # ------------------------------------------------------------------------
304             sub create_query_table {
305 4     4 0 9 my $self = shift;
306 4         8 my $arg_len = scalar @_;
307 4         10 my ($table_name, $col_list, $col_attr, $table_attr, $db_type);
308 4         7 my $data = '';
309 4         7 my $size_tblAttr = 0;
310 4         15 $db_type = $self->db_type;
311            
312 4 100       37 if ($arg_len == 3) {
313 1         3 ($table_name, $col_list, $col_attr) = @_;
314             }
315            
316 4 100       13 if ($arg_len == 4) {
317 3         10 ($table_name, $col_list, $col_attr, $table_attr) = @_;
318 3 50       12 if (ref($table_attr) eq "HASH") {
319 3         3 $size_tblAttr = scalar keys %{$table_attr};
  3         8  
320             } else {
321 0         0 $table_attr = {};
322             }
323             }
324            
325 4 50       17 if ($arg_len >= 5) {
326 0         0 ($table_name, $col_list, $col_attr, $table_attr, $self->db_type) = @_;
327 0         0 $size_tblAttr = scalar keys %{$table_attr};
  0         0  
328             }
329            
330 4         15 $col_attr = $self->table_col_attr_val($col_list, $col_attr);
331 4         18 $table_attr = $self->table_attr_val($col_attr, $table_attr);
332            
333 4         37 my $size_col = scalar @{$col_list};
  4         10  
334 4         7 my $i = 0;
335 4         16 my @list_col = ();
336 4         15 while ($i < $size_col) {
337 14         52 push @list_col, $self->create_colAttr($col_list->[$i], $col_attr->{$col_list->[$i]}, $self->db_type);
338 14         60 $i++;
339             }
340 4         14 my $list_column = join ",\n", @list_col;
341 4         8 my $fk_table = '';
342 4         6 my $index_table = '';
343 4         8 my $attr_table = '';
344            
345 4         12 $data .= "CREATE TABLE IF NOT EXISTS $table_name(\n";
346            
347 4 100       13 if ($size_tblAttr != 0) {
348 3         9 $data .= "$list_column";
349 3         11 my $size_fk = 0;
350 3 100       12 if (exists $table_attr->{fk}) {
351 2         4 $size_fk = 1;
352 2         4 $fk_table = $table_attr->{fk};
353 2         12 $data .= ",\n$fk_table";
354             }
355 3 50       13 if (exists $table_attr->{index}) {
356 0         0 $index_table = $table_attr->{index};
357 0         0 $data .= ",\n$index_table";
358             }
359 3 50 33     27 if (exists $table_attr->{attr} and $table_attr->{attr} ne '') {
360 3 100       17 if ($size_fk == 1) {
361 2         5 $attr_table = $table_attr->{attr};
362 2 100       14 $data .= $db_type eq 'sqlite' ? " \n)" : ") $attr_table";
363             }
364             else {
365 1 50       4 $data .= $db_type eq 'sqlite' ? " \n)" : ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
366             }
367             }
368             else {
369 0 0       0 $data .= $db_type eq 'sqlite' ? " \n)" : ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
370             }
371            
372             }
373             else {
374 1         4 $data .= "$list_column\n";
375 1 50       3 $data .= $db_type eq 'sqlite' ? ")" : ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
376             }
377 4         40 return $data;
378             }
379              
380             #######################################################################################
381             # FOR Helper
382             #######################################################################################
383              
384             # For check engine :
385             # ------------------------------------------------------------------------
386             sub _check_engine {
387 2     2   7 my ($self, $engine) = @_;
388            
389 2         11 $engine = lc $engine;
390 2         10 my %list_engine = (
391             'myisam' => 'MyISAM',
392             'innodb' => 'InnoDB',
393             );
394            
395 2 50       12 if (exists $list_engine{$engine}) {
396 2         9 return $list_engine{$engine};
397             }
398             else {
399 0           return $list_engine{'innodb'};
400             }
401             }
402              
403             1;