File Coverage

blib/lib/Data/Model/Schema.pm
Criterion Covered Total %
statement 179 182 98.3
branch 31 38 81.5
condition 23 39 58.9
subroutine 40 40 100.0
pod 15 16 93.7
total 288 315 91.4


line stmt bran cond sub pod time code
1             package Data::Model::Schema;
2 73     73   51051 use strict;
  73         168  
  73         3049  
3 73     73   491 use warnings;
  73         149  
  73         2121  
4              
5 73     73   382 use Carp ();
  73         133  
  73         1846  
6             $Carp::Internal{(__PACKAGE__)}++;
7 73     73   73762 use Encode ();
  73         1327231  
  73         1906  
8              
9 73     73   42393 use Data::Model::Row;
  73         232  
  73         3922  
10 73     73   46721 use Data::Model::Schema::Properties;
  73         350  
  73         9322  
11              
12             my $SUGAR_MAP = +{};
13             our $COLUMN_SUGAR = +{};
14              
15             sub import {
16 84     84   7846 my($class, %args) = @_;
17 84         332 my $caller = caller;
18 84   100     1093 $SUGAR_MAP->{$caller} = $args{sugar} || 'default';
19 84   100     702 $COLUMN_SUGAR->{$SUGAR_MAP->{$caller}} ||= +{};
20              
21 84 100       377 if ($caller eq 'Data::Model::Schema::Properties') {
22 2         4 $args{skip_import}++;
23             }
24              
25 84 100       325 unless ($args{skip_import}) {
26 73     73   583 no strict 'refs';
  73         156  
  73         7822  
27 82         240 for my $name (qw/ base_driver driver install_model schema column columns key index unique schema_options column_sugar
28             utf8_column utf8_columns alias_column add_method /) {
29 1230         1988 *{"$caller\::$name"} = \&$name;
  1230         5266  
30             }
31             }
32              
33 84         449 my $__properties = +{
34             base_driver => undef,
35             schema => +{},
36             __process_tmp => +{
37             class => $caller,
38             },
39             };
40              
41 73     73   480 no strict 'refs';
  73         154  
  73         2225  
42 73     73   397 no warnings 'redefine';
  73         186  
  73         21499  
43 84     4203   409 *{"$caller\::__properties"} = sub { $__properties };
  84         29657  
  4203         18858  
44             }
45              
46             my $CALLER = undef;
47             sub install_model ($$;%) {
48 175     175 1 411 my($name, $schema_code, %args) = @_;
49 175         352 my $caller = caller;
50              
51 175         723 my $pkg = "$caller\::$name";
52              
53 175         604 my $schema = $caller->__properties->{schema}->{$name} = Data::Model::Schema::Properties->new(
54             driver => $caller->__properties->{base_driver},
55             schema_class => $caller,
56             model => $name,
57             class => $pkg,
58             column => {},
59             columns => [],
60             index => {},
61             unique => {},
62             key => [],
63             foreign => [],
64             triggers => {},
65             options => {},
66             utf8_columns => {},
67             inflate_columns => [],
68             deflate_columns => [],
69             has_inflate => 0,
70             has_deflate => 0,
71             alias_column => {},
72             aluas_column_revers_map => {},
73             _build_tmp => {},
74             );
75              
76 175         748 $caller->__properties->{__process_tmp}->{name} = $name;
77 175         296 $CALLER = $caller;
78 175         590 $schema_code->();
79 167         643 $schema->setup_inflate;
80 167 100       636 unless ($schema->options->{bare_row}) {
81 73     73   433 no strict 'refs';
  73         177  
  73         12227  
82 166         272 @{"$pkg\::ISA"} = ( 'Data::Model::Row' );
  166         3924  
83 166         475 _install_columns_to_class($schema);
84 166         405 _install_alias_columns_to_class($schema);
85             }
86 167         319 $CALLER = undef;
87 167         515 delete $caller->__properties->{__process_tmp};
88              
89 167 100       544 if ($schema->driver) {
90 162         482 $schema->driver->attach_model($name, $schema);
91             }
92             }
93 175     175 1 1017 sub schema (&) { shift }
94              
95             sub _install_columns_to_class {
96 166     166   271 my $schema = shift;
97 73     73   544 no strict 'refs';
  73         162  
  73         27861  
98 166         382 while (my($column, $args) = each %{ $schema->column }) {
  577         1645  
99 411         1090 my $alias_list = $schema->aluas_column_revers_map->{$column};
100              
101 411 100       838 if ($alias_list) {
102 52         169 *{ $schema->class . "::$column" } = sub {
103 468     468   288452 my $obj = shift;
104             # getter
105 468 100       3186 return $obj->{column_values}->{$column} unless @_;
106             # setter
107 160         310 my($val, $flags) = @_;
108 160         412 my $old_val = $obj->{column_values}->{$column};
109 160         311 $obj->{column_values}->{$column} = $val;
110 160 0 33     509 unless ($flags && ref($flags) eq 'HASH' && $flags->{no_changed_flag}) {
      33        
111 160         437 $obj->{changed_cols}->{$column} = $old_val;
112             }
113 160         216 for my $alias (@{ $alias_list }) {
  160         369  
114 160         1251 delete $obj->{alias_values}->{$alias};
115             }
116 160         713 return $obj->{column_values}->{$column};
117 52         249 };
118             } else {
119 359         1045 *{ $schema->class . "::$column" } = sub {
120 2647     2647   496407 my $obj = shift;
121             # getter
122 2647 100       24564 return $obj->{column_values}->{$column} unless @_;
123             # setter
124 37         104 my($val, $flags) = @_;
125 37         134 my $old_val = $obj->{column_values}->{$column};
126 37         107 $obj->{column_values}->{$column} = $val;
127 37 0 33     3549 unless ($flags && ref($flags) eq 'HASH' && $flags->{no_changed_flag}) {
      33        
128 37         328 $obj->{changed_cols}->{$column} = $old_val;
129             }
130 37         131 return $obj->{column_values}->{$column};
131 359         1614 };
132             }
133             }
134             }
135              
136             sub _install_alias_columns_to_class {
137 166     166   258 my $schema = shift;
138 73     73   422 no strict 'refs';
  73         145  
  73         99802  
139 166         285 while (my($column, $args) = each %{ $schema->alias_column }) {
  218         647  
140 52         104 my $base = $args->{base};
141 52         80 my $deflate_code = $args->{deflate};
142 52         77 my $is_utf8 = $args->{is_utf8};
143 52   50     288 my $charset = $args->{charset} || 'utf8';
144 52         81 my $inflate2alias = $args->{inflate2alias};
145              
146 52 100 100     226 if ($is_utf8 && $deflate_code) {
    100          
    100          
147 16         62 *{ $schema->class . "::$column" } = sub {
148 136     136   46586 my $obj = shift;
149             # getter
150 136 100 66     1383 return $obj->{alias_values}->{$column} ||= $inflate2alias->($obj) unless @_;
151             # setter
152 24         171 $obj->{alias_values}->{$column} = $_[0];
153 24         158 $obj->$base( Encode::encode($charset, $deflate_code->( $_[0] ) ) );
154 24         130 return $_[0];
155 16         105 };
156             } elsif ($is_utf8) {
157 8         31 *{ $schema->class . "::$column" } = sub {
158 80     80   9241 my $obj = shift;
159             # getter
160 80 100 66     704 return $obj->{alias_values}->{$column} ||= $inflate2alias->($obj) unless @_;
161             # setter
162 16         63 $obj->{alias_values}->{$column} = $_[0];
163 16         110 $obj->$base( Encode::encode($charset, $_[0]) );
164 16         89 return $_[0];
165 8         47 };
166             } elsif ($deflate_code) {
167 20         85 *{ $schema->class . "::$column" } = sub {
168 156     156   27468 my $obj = shift;
169             # getter
170 156 100 66     1503 return $obj->{alias_values}->{$column} ||= $inflate2alias->($obj) unless @_;
171             # setter
172 28         92 $obj->{alias_values}->{$column} = $_[0];
173 28         370 $obj->$base( $deflate_code->($_[0]) );
174 28         111 return $_[0];
175 20         101 };
176             } else {
177 8         32 *{ $schema->class . "::$column" } = sub {
178 72     72   3707 my $obj = shift;
179             # getter
180 72 100 33     454 return $obj->{alias_values}->{$column} ||= $inflate2alias->($obj) unless @_;
181             # setter
182 24         74 $obj->{alias_values}->{$column} = $_[0];
183 24         91 $obj->$base( $_[0] );
184 24         107 return $_[0];
185 8         48 };
186             }
187             }
188             }
189              
190             sub _get_model_schema {
191 731 50   731   1682 if ($CALLER) {
192 731         1129 my $caller = caller(1);
193 731         1867 my $name = $caller->__properties->{__process_tmp}->{name};
194 731         1523 return ($name, $caller->__properties->{schema}->{$name});
195             }
196              
197 0         0 my $method = (caller(1))[3];
198 0         0 $method =~ s/.+:://;
199 0         0 Carp::croak "'$method' method is target internal only";
200             }
201              
202             sub base_driver ($) {
203 15     15 1 97 my $caller = caller;
204 15 50       572 return unless $caller->can('__properties');
205 15         72 $caller->__properties->{base_driver} = shift;
206             }
207              
208             sub driver ($;%) {
209 147     147 1 606 my($name, $schema) = _get_model_schema;
210 147         292 my($driver, %args) = @_;
211 147         578 $schema->driver($driver);
212             }
213              
214             sub column ($;$;$) {
215 231     231 1 1177 my($name, $schema) = _get_model_schema;
216 231         987 $schema->add_column(@_);
217             }
218             sub columns (@) {
219 62     62 1 284 my($name, $schema) = _get_model_schema;
220 62         165 my @columns = @_;
221 62         130 for my $column (@columns) {
222 154         483 $schema->add_column($column);
223             }
224             }
225             sub utf8_column ($;$;$) {
226 24     24 1 135 my($name, $schema) = _get_model_schema;
227 24         217 $schema->add_utf8_column(@_);
228             }
229             sub utf8_columns (@) {
230 8     8 1 47 my($name, $schema) = _get_model_schema;
231 8         22 my @columns = @_;
232 8         20 for my $column (@columns) {
233 12         66 $schema->add_utf8_column($column);
234             }
235             }
236              
237             sub alias_column {
238 24     24 1 190 my($name, $schema) = _get_model_schema;
239 24         85 $schema->add_alias_column(@_);
240             }
241              
242             sub key ($;%) {
243 158     158 1 649 my($name, $schema) = _get_model_schema;
244 158         635 $schema->add_keys(@_);
245             }
246              
247             sub index ($;$;%) {
248 42     42 1 236 my($name, $schema) = _get_model_schema;
249 42         304 $schema->add_index(@_);
250             }
251              
252             sub unique ($;$;%) {
253 18     18 1 94 my($name, $schema) = _get_model_schema;
254 18         96 $schema->add_unique(@_);
255             }
256              
257             sub schema_options (@) {
258 16     16 1 80 my($name, $schema) = _get_model_schema;
259 16         68 $schema->add_options(@_);
260             }
261              
262             sub add_method {
263 1     1 1 10 my($name, $schema) = _get_model_schema;
264 1         3 my($method, $code) = @_;
265 73     73   534 no strict 'refs';
  73         171  
  73         20969  
266 1         2 *{$schema->class."::$method"} = $code;
  1         8  
267             }
268              
269              
270             sub column_sugar (@) {
271 66     66 1 475 my($column, $type, $options) = @_;
272 66 50       407 Carp::croak "usage: add_column_sugar 'table_name.column_name' => type => { args };"
273             unless $column =~ /^[^\.+]+\.[^\.+]+$/;
274              
275 66         119 my $caller = caller;
276 66   50     203 $COLUMN_SUGAR->{$SUGAR_MAP->{$caller}} ||= +{};
277 66   50     502 $COLUMN_SUGAR->{$SUGAR_MAP->{$caller}}->{$column} = +{
      100        
278             type => $type || 'char',
279             options => $options || +{},
280             };
281             }
282              
283             sub get_column_sugar {
284 86     86 0 132 my($class, $schema) = @_;
285 86         296 $COLUMN_SUGAR->{$SUGAR_MAP->{$schema->{schema_class}}};
286             }
287              
288             1;
289              
290             __END__