File Coverage

blib/lib/Types/SQL/Util.pm
Criterion Covered Total %
statement 40 40 100.0
branch 24 26 92.3
condition 6 8 75.0
subroutine 6 6 100.0
pod 1 1 100.0
total 77 81 95.0


line stmt bran cond sub pod time code
1             package Types::SQL::Util;
2              
3 17     17   1055208 use strict;
  17         93  
  17         446  
4 17     17   79 use warnings;
  17         33  
  17         563  
5              
6 17     17   80 use Exporter 5.57 qw/ import /;
  17         253  
  17         527  
7              
8 17     17   2935 use PerlX::Maybe qw/ maybe /;
  17         16133  
  17         82  
9 17     17   7093 use Safe::Isa 1.000008 qw/ $_isa $_call_if_can /;
  17         7508  
  17         15572  
10              
11             our $VERSION = 'v0.6.1';
12              
13             # RECOMMEND PREREQ: PerlX::Maybe::XS
14              
15             # ABSTRACT: extract DBIx::Class column_info from types
16              
17              
18             our @EXPORT = qw/ column_info_from_type /;
19             our @EXPORT_OK = @EXPORT;
20              
21             my %CLASS_TYPES = (
22             'Data::UUID' => 'uuid',
23             'Data::GUID' => 'uuid',
24             'Date' => 'timestamp',
25             'DateTime' => 'timestamp',
26             'DateTime::Tiny' => 'timestamp',
27             'JSON::PP::Boolean' => 'boolean',
28             'Time::Moment' => 'timestamp',
29             'Time::Piece' => 'timestamp',
30             'Types::Serialiser::Boolean' => 'boolean',
31             );
32              
33              
34             my %FROM_PARENT = (
35              
36             'Types::Standard' => {
37              
38             'ArrayRef' => sub {
39             my %type = column_info_from_type( $_[0]->type_parameter );
40             $type{data_type} .= '[]';
41             return %type;
42             },
43              
44             'Maybe' => sub {
45             return (
46             is_nullable => 1,
47             column_info_from_type( $_[0]->type_parameter )
48             );
49             },
50              
51             'Object' => sub {
52             my $class = $_[0]->$_call_if_can('class') or return;
53             if ( my $data_type = $CLASS_TYPES{$class} ) {
54             return ( data_type => $data_type );
55             }
56             return;
57             },
58              
59             }
60              
61             );
62              
63             my %FROM_TYPE = (
64              
65             'Types::Standard' => {
66              
67             'Bool' => sub {
68             return ( data_type => 'boolean' );
69             },
70              
71             'Int' => sub {
72             return ( data_type => 'integer', is_numeric => 1 );
73             },
74              
75             'Num' => sub {
76             return ( data_type => 'numeric', is_numeric => 1 );
77             },
78              
79              
80             'Str' => sub {
81             return ( data_type => 'text', is_numeric => 0 );
82             },
83              
84             },
85              
86             'Types::Common::Numeric' => {
87              
88             'PositiveInt' => sub {
89             return (
90             data_type => 'integer',
91             is_numeric => 1,
92             extra => { unsigned => 1 }
93             );
94             },
95              
96             'PositiveOrZeroInt' => sub {
97             return (
98             data_type => 'integer',
99             is_numeric => 1,
100             extra => { unsigned => 1 }
101             );
102             },
103              
104             'PositiveNum' => sub {
105             return (
106             data_type => 'numeric',
107             is_numeric => 1,
108             extra => { unsigned => 1 }
109             );
110             },
111              
112             'PositiveOrZeroNum' => sub {
113             return (
114             data_type => 'numeric',
115             is_numeric => 1,
116             extra => { unsigned => 1 }
117             );
118             },
119              
120             'SingleDigit' => sub {
121             return (
122             data_type => 'integer',
123             is_numeric => 1,
124             size => 1,
125             extra => { unsigned => 1 }
126             );
127             },
128              
129             },
130              
131             'Types::Common::String' => {
132              
133             'LowerCaseStr' => sub {
134             return ( data_type => 'text', is_numeric => 0 );
135             },
136              
137             'UpperCaseStr' => sub {
138             return ( data_type => 'text', is_numeric => 0 );
139             },
140              
141             'NonEmptyStr' => sub {
142             return ( data_type => 'text', is_numeric => 0 );
143             },
144              
145             'LowerCaseSimpleStr' => sub {
146             return ( data_type => 'text', is_numeric => 0, size => 255 );
147             },
148              
149             'UpperCaseSimpleStr' => sub {
150             return ( data_type => 'text', is_numeric => 0, size => 255 );
151             },
152              
153             'NonEmptySimpleStr' => sub {
154             return ( data_type => 'text', is_numeric => 0, size => 255 );
155             },
156              
157             'SimpleStr' => sub {
158             return ( data_type => 'text', is_numeric => 0, size => 255 );
159             },
160              
161             },
162              
163             'Types::DateTime' => {
164              
165             'DateTime' => sub {
166             return ( data_type => 'timestamp' );
167             },
168              
169             'DateTimeWithZone' => sub {
170             return ( data_type => 'timestamp with time zone' );
171             },
172              
173             'DateTimeUTC' => sub {
174             return ( data_type => 'timestamp with time zone' );
175             },
176              
177             'Now' => sub {
178             return ( data_type => 'timestamp', default_value => \ "CURRENT_TIMESTAMP" );
179             },
180             },
181              
182             'Types::UUID' => {
183              
184             'Uuid' => sub {
185             return ( data_type => 'uuid' ),
186             },
187              
188             },
189              
190             );
191              
192              
193             sub column_info_from_type {
194 88     88 1 178228 my ($type) = @_;
195              
196 88 50       351 return { } unless $type->$_isa('Type::Tiny');
197              
198 88         1944 my $name = $type->name;
199 88         755 my $methods = $type->my_methods;
200 88 100       556 my $parent = $type->has_parent ? $type->parent : undef;
201              
202 88 100 66     854 if ( $type->is_anon && $parent ) {
203 46         721 $name = $parent->name;
204 46         201 $methods = $parent->my_methods;
205             }
206              
207 88 100 66     783 if ( $methods && $methods->{dbic_column_info} ) {
208 16         84 return $methods->{dbic_column_info}->($type);
209             }
210              
211 72 100 100     188 my $from = ( $type->library ? $FROM_TYPE{ $type->library } : undef ) // { };
212              
213 72 100       658 if ( my $code = $from->{$name} ) {
214 29 50       139 if ( my %info = $code->($type) ) {
215 29         199 return %info;
216             }
217             }
218              
219 43 100       124 if ( $type->isa('Type::Tiny::Enum') ) {
220             return (
221 2         17 data_type => 'enum',
222             is_enum => 1,
223             is_numeric => 0,
224             extra => {
225             list => $type->values,
226             },
227             );
228             }
229              
230 41 100       468 if ( my $parent_lib = $parent->$_call_if_can('library') ) {
231 39 100       1003 if ( my $code = $FROM_PARENT{$parent_lib}{$name} ) {
232 36 100       114 if ( my %info = $code->($type) ) {
233 35         211 return %info;
234             }
235             }
236             }
237              
238 6 100       78 if ( $parent ) {
239 5         28 my @info = eval { column_info_from_type( $parent ) };
  5         34  
240 5 100       50 return @info if @info;
241             }
242              
243 5         10 die "Unsupported type: " . $type->display_name;
244             }
245              
246              
247             1;
248              
249             __END__