File Coverage

lib/CellBIS/SQL/Abstract/Table.pm
Criterion Covered Total %
statement 223 262 85.1
branch 78 124 62.9
condition 19 47 40.4
subroutine 11 12 91.6
pod 0 7 0.0
total 331 452 73.2


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