line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojolicious::Plugin::Tables::Model; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
24
|
use strict; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
92
|
|
4
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
103
|
|
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
17
|
use base qw/DBIx::Class::Schema/; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
2064
|
|
7
|
3
|
|
|
3
|
|
178280
|
use DBIx::Class::Schema::Loader::Dynamic; |
|
3
|
|
|
|
|
536708
|
|
|
3
|
|
|
|
|
3920
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
__PACKAGE__->mk_group_accessors(inherited => qw/log connect_info model/); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub setup { |
12
|
3
|
|
|
3
|
0
|
9
|
my ($class, $conf) = @_; |
13
|
3
|
50
|
|
|
|
16
|
if (my $connect_info = $conf->{connect_info}) { |
14
|
3
|
|
|
|
|
65
|
$class->connect_info($connect_info) |
15
|
|
|
|
|
|
|
} else { |
16
|
0
|
0
|
|
|
|
0
|
die "Provide connect_info either as a config value or an override" |
17
|
|
|
|
|
|
|
unless $class->connect_info |
18
|
|
|
|
|
|
|
} |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# to return a schema object-ref here say 'connect' instead of 'connection'. |
21
|
3
|
|
|
|
|
85
|
my $schema = $class->connection(@{$class->connect_info}); |
|
3
|
|
|
|
|
63
|
|
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
DBIx::Class::Schema::Loader::Dynamic->new( |
24
|
|
|
|
|
|
|
left_base_classes => $class->row_base, |
25
|
|
|
|
|
|
|
rel_name_map => $class->rel_name_map, |
26
|
27
|
|
|
27
|
|
777040
|
custom_column_info => sub { $class->custom_column_info(@_) }, |
27
|
|
|
|
|
|
|
naming => 'v8', |
28
|
|
|
|
|
|
|
use_namespaces => 0, |
29
|
|
|
|
|
|
|
schema => $schema, |
30
|
3
|
50
|
|
|
|
269910
|
%{$conf->{loader_opts}||{}}, |
|
3
|
|
|
|
|
48
|
|
31
|
|
|
|
|
|
|
)->load; |
32
|
|
|
|
|
|
|
|
33
|
3
|
|
|
|
|
119510
|
$schema->model($schema->_model); |
34
|
|
|
|
|
|
|
|
35
|
3
|
|
|
|
|
68
|
return $schema; |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
|
38
|
3
|
|
|
3
|
0
|
40
|
sub row_base { 'Mojolicious::Plugin::Tables::Model::Row' } |
39
|
|
|
|
|
|
|
|
40
|
48
|
|
|
48
|
1
|
219
|
sub glossary { +{ id => 'Identifier' } } |
41
|
|
|
|
|
|
|
|
42
|
27
|
|
|
27
|
1
|
177
|
sub input_attrs { +{ name => { size=>80 } } } |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub make_label { |
45
|
48
|
|
|
48
|
0
|
101
|
my $self = shift; |
46
|
48
|
|
|
|
|
95
|
my $name = shift; |
47
|
48
|
|
|
|
|
136
|
my @label = split '_', $name; |
48
|
48
|
|
|
|
|
118
|
for (@label) { |
49
|
48
|
50
|
|
|
|
115
|
$_ = $self->glossary->{$_}, next if $self->glossary->{$_}; |
50
|
48
|
|
|
|
|
160
|
$_ = ucfirst |
51
|
|
|
|
|
|
|
} |
52
|
48
|
|
|
|
|
229
|
join(' ', @label) |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
sub custom_column_info { |
56
|
27
|
|
|
27
|
0
|
72
|
my ($class, $table, $column, $column_info) = @_; |
57
|
27
|
|
|
|
|
73
|
my $info = { label => $class->make_label($column) }; |
58
|
27
|
|
|
|
|
53
|
my $attrs1; |
59
|
27
|
|
|
|
|
63
|
for ($column_info->{data_type}) { |
60
|
27
|
100
|
|
|
|
216
|
$attrs1 = |
|
|
50
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
61
|
|
|
|
|
|
|
/numeric|integer/ ? {type=>'number'} : |
62
|
|
|
|
|
|
|
/timestamp/ ? {type=>'datetime-local'} : |
63
|
|
|
|
|
|
|
/date|time/ ? {type=>$_} : |
64
|
|
|
|
|
|
|
{}; |
65
|
|
|
|
|
|
|
} |
66
|
27
|
|
100
|
|
|
74
|
my $attrs2 = $class->input_attrs->{$column} || {}; |
67
|
27
|
100
|
100
|
|
|
189
|
$info->{input_attrs} = {%$attrs1, %$attrs2} if keys(%$attrs1) || keys(%$attrs2); |
68
|
27
|
|
|
|
|
102
|
$info |
69
|
|
|
|
|
|
|
}; |
70
|
|
|
|
|
|
|
|
71
|
3
|
|
|
3
|
1
|
23
|
sub rel_name_map { +{} } |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
sub _model { |
74
|
3
|
|
|
3
|
|
444
|
my $schema = shift; |
75
|
|
|
|
|
|
|
|
76
|
3
|
|
|
|
|
12
|
my @tablist = (); |
77
|
3
|
|
|
|
|
10
|
my %bytable = (); |
78
|
|
|
|
|
|
|
#my $log = $schema->log; |
79
|
|
|
|
|
|
|
#$log->debug("$schema is building its model"); |
80
|
3
|
|
|
|
|
28
|
for my $source (sort $schema->sources) { |
81
|
9
|
|
|
|
|
191
|
my $s = $schema->source($source); |
82
|
9
|
|
|
|
|
432
|
my @has_a; |
83
|
|
|
|
|
|
|
my %has_many; |
84
|
9
|
|
|
|
|
49
|
for my $rel ($s->relationships) { |
85
|
12
|
|
|
|
|
93
|
my $info = $s->relationship_info($rel); |
86
|
12
|
|
|
|
|
175
|
my $ftable = $info->{class}->table; |
87
|
12
|
|
|
|
|
524
|
my $attrs = $info->{attrs}; |
88
|
12
|
|
|
|
|
32
|
my $card = $attrs->{accessor}; |
89
|
12
|
100
|
|
|
|
53
|
if ($card eq 'single') { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
90
|
6
|
|
|
|
|
15
|
my $fks = $attrs->{fk_columns}; |
91
|
6
|
|
|
|
|
27
|
my @fks = keys %$fks; |
92
|
6
|
50
|
|
|
|
39
|
push @has_a, { fkey=>$fks[0], parent=>$rel, label=>$schema->make_label($rel), ptable=>$ftable } |
93
|
|
|
|
|
|
|
if @fks == 1 |
94
|
|
|
|
|
|
|
} elsif ($card eq 'filter') { |
95
|
0
|
|
|
|
|
0
|
my @ffkeys = keys %{$info->{cond}}; |
|
0
|
|
|
|
|
0
|
|
96
|
0
|
0
|
|
|
|
0
|
if (@ffkeys == 1) { |
97
|
0
|
|
|
|
|
0
|
(my $cfkey = $ffkeys[0]) =~ s/^foreign\.//; |
98
|
0
|
|
|
|
|
0
|
push @has_a, { fkey=>$cfkey, parent=>$rel, label=>$schema->make_label($rel), ptable=>$ftable } |
99
|
|
|
|
|
|
|
} else { |
100
|
0
|
|
|
|
|
0
|
warn __PACKAGE__." model: $source: $rel: multi-barrelled M-1 keys not supported\n" |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} elsif ($card eq 'multi') { |
103
|
6
|
|
|
|
|
17
|
my $fsource_name = $info->{source}; |
104
|
6
|
|
|
|
|
24
|
my $fsource = $schema->source($fsource_name); |
105
|
6
|
|
|
|
|
462
|
my $fpkey = join(',', $fsource->primary_columns); |
106
|
6
|
|
|
|
|
56
|
my @ffkeys = keys %{$info->{cond}}; |
|
6
|
|
|
|
|
26
|
|
107
|
6
|
50
|
|
|
|
29
|
if (@ffkeys == 1) { |
108
|
6
|
|
|
|
|
31
|
(my $cfkey = $ffkeys[0]) =~ s/^foreign\.//; |
109
|
6
|
|
|
|
|
96
|
$has_many{$rel} = {ctable=>$ftable, cpkey=>$fpkey, cfkey=>$cfkey, label=>$schema->make_label($rel)}; |
110
|
|
|
|
|
|
|
} else { |
111
|
0
|
|
|
|
|
0
|
warn __PACKAGE__." model: $source: $rel: multi-barrelled 1-M keys not supported\n" |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
} else { |
114
|
0
|
|
|
|
|
0
|
warn __PACKAGE__." model: $source: $rel: strange cardinality: $card\n"; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
my %bycolumn = map { |
118
|
9
|
|
|
|
|
65
|
my %info = %{$s->column_info($_)}; |
|
27
|
|
|
|
|
123
|
|
|
27
|
|
|
|
|
64
|
|
119
|
27
|
|
|
|
|
366
|
delete $info{name}; |
120
|
27
|
|
100
|
|
|
177
|
/^_/ && delete $info{$_} for keys %info; |
121
|
27
|
|
|
|
|
100
|
( $_ => \%info ) |
122
|
|
|
|
|
|
|
} $s->columns; |
123
|
9
|
|
|
|
|
38
|
for (@has_a) { |
124
|
6
|
|
|
|
|
16
|
my $fkey = $_->{fkey}; |
125
|
6
|
|
|
|
|
15
|
my $parent = delete $_->{parent}; |
126
|
6
|
50
|
|
|
|
28
|
$bycolumn{$fkey}->{parent} = $parent if $bycolumn{$fkey}; |
127
|
6
|
|
|
|
|
17
|
$bycolumn{$parent} = $_; # gets {fkey=>, label=>, ptable=>,} |
128
|
|
|
|
|
|
|
} |
129
|
9
|
|
|
|
|
31
|
my $pkeys = [$s->primary_columns]; |
130
|
9
|
|
|
|
|
87
|
my $pknum = 0; |
131
|
9
|
|
|
|
|
23
|
for (@$pkeys) { |
132
|
9
|
|
|
|
|
27
|
$bycolumn{$_}{is_primary_key} = ++$pknum |
133
|
|
|
|
|
|
|
} |
134
|
9
|
100
|
|
|
|
31
|
my @columns = map { $_, $bycolumn{$_}{parent}? ($bycolumn{$_}{parent}): () } |
|
27
|
|
|
|
|
146
|
|
135
|
|
|
|
|
|
|
$s->columns; |
136
|
9
|
|
|
|
|
42
|
my $label = $schema->make_label($s->name); |
137
|
9
|
|
|
|
|
55
|
my $tabinfo = { |
138
|
|
|
|
|
|
|
source => $source, |
139
|
|
|
|
|
|
|
columns => \@columns, |
140
|
|
|
|
|
|
|
bycolumn => \%bycolumn, |
141
|
|
|
|
|
|
|
has_many => \%has_many, |
142
|
|
|
|
|
|
|
label => $label, |
143
|
|
|
|
|
|
|
pkeys => $pkeys, |
144
|
|
|
|
|
|
|
}; |
145
|
9
|
|
|
|
|
63
|
push @tablist, $s->name; |
146
|
9
|
|
|
|
|
44
|
$bytable{$s->name} = $tabinfo; |
147
|
|
|
|
|
|
|
} |
148
|
3
|
|
|
|
|
115
|
return {schema=>$schema, tablist=>\@tablist, bytable=>\%bytable}; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
1; |
152
|
|
|
|
|
|
|
__END__ |