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   53 use Mojo::Base -base;
  10         14  
  10         51  
4              
5 10     10   1133 use Scalar::Util qw(blessed);
  10         21  
  10         360  
6 10     10   43 use Mojo::Util qw(trim);
  10         16  
  10         274  
7 10     10   3772 use Hash::MultiValue;
  10         14648  
  10         19784  
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         11 my $fk = $table_attr->{fk};
23 2 50 33     14 if (exists $fk->{name} && $fk->{name} ne '') {
24 2         12 $fk_attr{name} = 1;
25             }
26 2 50 33     12 if (exists $fk->{col_name} && $fk->{col_name} ne '') {
27 2         3 $fk_attr{col_name} = 1;
28             }
29            
30 2 50 33     10 if (exists $fk->{table_target} && $fk->{table_target} ne '') {
31 2         5 $fk_attr{table_target} = 1;
32             }
33            
34 2 50 33     12 if (exists $fk->{col_target} && $fk->{col_target} ne '') {
35 2         4 $fk_attr{col_target} = 1;
36             }
37 2         7 my @r_val = grep {!$_} values %fk_attr;
  8         16  
38 2         3 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       8 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 7 my ($fk_table) = @_;
59 2         4 my $data = '';
60 2         10 my %ondelup = (
61             'cascade' => 'CASCADE',
62             'null' => 'SET NULL',
63             'default' => 'SET DEFAULT'
64             );
65 2         28 my $ondel = 0;
66 2 50       28 if (exists $fk_table->{ondelete}) {
67 2 50       14 if (exists $ondelup{(lc $fk_table->{ondelete})}) {
68 2         3 $ondel = 1;
69 2         9 $data .= 'ON DELETE ' . $ondelup{(lc $fk_table->{ondelete})};
70             }
71             }
72            
73 2 50       8 if (exists $fk_table->{onupdate}) {
74 2 50       6 if (exists $ondelup{(lc $fk_table->{onupdate})}) {
75 2 50       8 $data .= ' ' if $ondel == 1;
76 2         7 $data .= 'ON UPDATE ' . $ondelup{(lc $fk_table->{onupdate})};
77             }
78             }
79 2         10 $data = trim($data);
80 2         27 return $data;
81             }
82              
83             # For Table Attribute Validator :
84             # ------------------------------------------------------------------------
85             sub table_attr_val {
86 4     4 0 10 my $self = shift;
87 4         11 my ($col_attr, $table_attr) = @_;
88 4         9 my $new_tblAttr = {};
89 4         7 my $attrib_table = '';
90 4   50     14 my $db_type = $self->db_type // 'mysql';
91            
92 4 100       30 if (exists $table_attr->{fk}) {
93 2         6 $table_attr = fk_validator($table_attr, $col_attr);
94 2         4 my $table_fk = '';
95 2 50       7 if (exists $table_attr->{fk}) {
96 2         4 my $fk_table = $table_attr->{fk};
97 2         18 my $fk_name = $fk_table->{name};
98 2         5 my $col_name = $fk_table->{col_name};
99 2         4 my $table_target = $fk_table->{table_target};
100 2         4 my $col_target = $fk_table->{col_target};
101 2         4 my $fk_attr = '';
102 2 50       18 if ($fk_table->{attr}) {
103 2         7 $fk_attr = fk_attr_validator($fk_table->{attr});
104             }
105 2 100       7 if ($db_type eq 'sqlite') {
106 1         4 $table_fk .= "\tCONSTRAINT $fk_name ";
107 1         2 $table_fk .= "FOREIGN KEY ($col_name) ";
108 1 50       4 $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       6 $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         65 $new_attrTbl->set(fk => $table_fk);
120 2         35 $table_attr = $new_attrTbl->as_hashref;
121             }
122             }
123 4 50       44 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       12 if (exists $table_attr->{engine}) {
134 2         3 $engine = 1;
135 2         17 my $r_engine = $self->_check_engine($table_attr->{engine});
136 2         8 $attrib_table .= 'ENGINE=' . $r_engine;
137             }
138 4 100       17 $attrib_table .= ' ' if ($engine == 1);
139             $attrib_table .= exists $table_attr->{charset} ?
140 4 100       17 'DEFAULT CHARSET=' . $table_attr->{charset} : 'DEFAULT CHARSET=utf8';
141 4         8 $new_tblAttr = Hash::MultiValue->new(%{$table_attr});
  4         16  
142 4         114 $new_tblAttr->set(attr => $attrib_table);
143 4         78 $table_attr = $new_tblAttr->as_hashref;
144            
145 4         46 return $table_attr;
146             }
147              
148             # For Column Attribute validator :
149             # ------------------------------------------------------------------------
150             sub table_col_attr_val {
151 4     4 0 7 my $self = shift;
152 4         13 my ($col_list, $col_attr) = @_;
153            
154 4 50       14 if (ref($col_attr) eq "HASH") {
155 4         8 my $i = 0;
156 4         5 my $until = scalar @{$col_list};
  4         9  
157 4         9 my @pk_list = ();
158 4         8 my @ai_list = ();
159 4         7 my $size_pk = 0;
160 4         6 my $size_ai = 0;
161 4         9 my $col_name = '';
162 4         5 my $curr_colAttr = {};
163 4         9 my $new_colAttr = Hash::MultiValue->new(%{$col_attr});
  4         36  
164 4         235 while ($i < $until) {
165 14         24 $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         9 push @ai_list, $col_list->[$i];
169 4         6 $curr_colAttr = Hash::MultiValue->new(%{$col_name});
  4         16  
170 4         132 $curr_colAttr->remove('is_autoincre');
171            
172 4         180 $new_colAttr->set($col_list->[$i] => $curr_colAttr->as_hashref);
173             }
174 14         117 $i++;
175             }
176 4         12 $col_attr = $new_colAttr->as_hashref;
177            
178 4         27 $i = 0;
179 4         11 while ($i < $until) {
180 14         22 $col_name = $col_attr->{$col_list->[$i]};
181 14 100       25 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         15  
185 4         157 $curr_colAttr->remove('is_primarykey');
186            
187 4         107 $new_colAttr->set($col_list->[$i] => $curr_colAttr->as_hashref);
188             }
189 14         97 $i++;
190             }
191            
192 4 50       11 if ($size_pk >= 1) {
193 4         11 my $r_colAttr = $new_colAttr->as_hashref;
194 4         27 my $pk_table = $r_colAttr->{$pk_list[0]};
195            
196 4         7 $curr_colAttr = Hash::MultiValue->new(%{$pk_table});
  4         12  
197 4         144 $curr_colAttr->set('is_primarykey' => 1);
198            
199 4         75 $col_attr = Hash::MultiValue->new(%{$r_colAttr});
  4         12  
200 4         127 $col_attr->set($pk_list[0] => $curr_colAttr->as_hashref);
201 4         86 $col_attr = $col_attr->as_hashref;
202             }
203            
204 4 50       52 if ($size_ai >= 1) {
205 4         10 my $pk_table = $col_attr->{$pk_list[0]};
206            
207 4         6 $curr_colAttr = Hash::MultiValue->new(%{$pk_table});
  4         21  
208 4         129 $curr_colAttr->set('is_autoincre' => 1);
209            
210 4         71 $col_attr = Hash::MultiValue->new(%{$col_attr});
  4         30  
211 4         132 $col_attr->set($pk_list[0] => $curr_colAttr->as_hashref);
212 4         89 $col_attr = $col_attr->as_hashref;
213             }
214            
215 4         45 $i = 0;
216 4         9 $new_colAttr = Hash::MultiValue->new();
217 4         104 while ($i < $until) {
218 14         25 $col_name = $col_attr->{$col_list->[$i]};
219            
220 14         53 $new_colAttr->add($col_list->[$i] => $col_name);
221 14         309 $i++;
222             }
223 4         11 $col_attr = $new_colAttr->as_hashref;
224             }
225 4         97 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 57 my $self = shift;
248 14         22 my ($col_name, $attr, $db_type) = @_;
249 14         29 my $data = $col_name . ' ';
250            
251 14 50       25 if (exists $attr->{type}) {
252 14 100       26 if ($db_type eq 'sqlite') {
253 7 50       22 $data .= exists $attr->{type}->{name} ? (uc $attr->{type}->{name}) . ' ' : 'varchar ';
254             } else {
255 7 50       26 $data .= exists $attr->{type}->{name} ? (uc $attr->{type}->{name}) : 'varchar';
256 7 50       27 $data .= exists $attr->{type}->{size} ? '(' . $attr->{type}->{size} . ') ' : ' ';
257             }
258             }
259            
260 14 50       73 unless (exists $attr->{custom}) {
261 14 50 33     49 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     39 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       29 $data .= 'NOT NULL ' if $attr->{is_null} eq 0;
278 10 50       22 $data .= 'NULL ' if $attr->{is_null} eq 1;
279             }
280             else {
281 4         9 $data .= 'NOT NULL ';
282             }
283            
284 14 100 66     40 if (exists $attr->{is_primarykey} and $attr->{is_primarykey} == 1) {
285 4         22 $data .= 'PRIMARY KEY ';
286             }
287            
288 14 100 66     41 if (exists $attr->{is_autoincre} and $attr->{is_autoincre} == 1) {
289 4 100       14 if ($db_type eq 'sqlite') {
290 2         6 $data .= 'AUTOINCREMENT ';
291             }
292             else {
293 2         5 $data .= 'AUTO_INCREMENT ';
294             }
295             }
296             }
297 14         34 $data = trim($data);
298 14         144 $data = "\t$data";
299 14         38 return $data;
300             }
301              
302             # For create query table :
303             # ------------------------------------------------------------------------
304             sub create_query_table {
305 4     4 0 10 my $self = shift;
306 4         9 my $arg_len = scalar @_;
307 4         10 my ($table_name, $col_list, $col_attr, $table_attr, $db_type);
308 4         9 my $data = '';
309 4         7 my $size_tblAttr = 0;
310 4         15 $db_type = $self->db_type;
311            
312 4 100       38 if ($arg_len == 3) {
313 1         2 ($table_name, $col_list, $col_attr) = @_;
314             }
315            
316 4 100       14 if ($arg_len == 4) {
317 3         11 ($table_name, $col_list, $col_attr, $table_attr) = @_;
318 3 50       13 if (ref($table_attr) eq "HASH") {
319 3         4 $size_tblAttr = scalar keys %{$table_attr};
  3         10  
320             } else {
321 0         0 $table_attr = {};
322             }
323             }
324            
325 4 50       12 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         19 $col_attr = $self->table_col_attr_val($col_list, $col_attr);
331 4         15 $table_attr = $self->table_attr_val($col_attr, $table_attr);
332            
333 4         28 my $size_col = scalar @{$col_list};
  4         8  
334 4         5 my $i = 0;
335 4         16 my @list_col = ();
336 4         19 while ($i < $size_col) {
337 14         46 push @list_col, $self->create_colAttr($col_list->[$i], $col_attr->{$col_list->[$i]}, $self->db_type);
338 14         30 $i++;
339             }
340 4         12 my $list_column = join ",\n", @list_col;
341 4         7 my $fk_table = '';
342 4         7 my $index_table = '';
343 4         6 my $attr_table = '';
344            
345 4         12 $data .= "CREATE TABLE IF NOT EXISTS $table_name(\n";
346            
347 4 100       14 if ($size_tblAttr != 0) {
348 3         7 $data .= "$list_column";
349 3         6 my $size_fk = 0;
350 3 100       10 if (exists $table_attr->{fk}) {
351 2         11 $size_fk = 1;
352 2         5 $fk_table = $table_attr->{fk};
353 2         6 $data .= ",\n$fk_table";
354             }
355 3 50       10 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     18 if (exists $table_attr->{attr} and $table_attr->{attr} ne '') {
360 3 100       14 if ($size_fk == 1) {
361 2         4 $attr_table = $table_attr->{attr};
362 2 100       13 $data .= $db_type eq 'sqlite' ? " \n)" : ") $attr_table";
363             }
364             else {
365 1 50       10 $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         3 $data .= "$list_column\n";
375 1 50       5 $data .= $db_type eq 'sqlite' ? ")" : ") ENGINE=InnoDB DEFAULT CHARSET=utf8";
376             }
377 4         33 return $data;
378             }
379              
380             #######################################################################################
381             # FOR Helper
382             #######################################################################################
383              
384             # For check engine :
385             # ------------------------------------------------------------------------
386             sub _check_engine {
387 2     2   5 my ($self, $engine) = @_;
388            
389 2         5 $engine = lc $engine;
390 2         7 my %list_engine = (
391             'myisam' => 'MyISAM',
392             'innodb' => 'InnoDB',
393             );
394            
395 2 50       13 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;