File Coverage

blib/lib/Geoffrey/Converter/SQLite.pm
Criterion Covered Total %
statement 126 126 100.0
branch 23 26 88.4
condition 16 24 66.6
subroutine 40 40 100.0
pod 17 17 100.0
total 222 233 95.2


line stmt bran cond sub pod time code
1             package Geoffrey::Converter::SQLite;
2              
3 19     19   550618 use utf8;
  19         188  
  19         117  
4 19     19   880 use 5.016;
  19         95  
5 19     19   123 use strict;
  19         41  
  19         397  
6 19     19   7066 use Readonly;
  19         53183  
  19         1015  
7 19     19   150 use warnings;
  19         38  
  19         996  
8              
9             $Geoffrey::Converter::SQLite::VERSION = '0.000203';
10              
11 19     19   3813 use parent 'Geoffrey::Role::Converter';
  19         2184  
  19         118  
12              
13             Readonly::Scalar my $I_CONST_LENGTH_VALUE => 2;
14             Readonly::Scalar my $I_CONST_NOT_NULL_VALUE => 3;
15             Readonly::Scalar my $I_CONST_PRIMARY_KEY_VALUE => 4;
16             Readonly::Scalar my $I_CONST_DEFAULT_VALUE => 5;
17              
18             {
19              
20             package Geoffrey::Converter::SQLite::Constraints;
21              
22 19     19   2017 use parent 'Geoffrey::Role::ConverterType';
  19         45  
  19         131  
23              
24             sub new {
25 4     4   10 my $class = shift;
26 4         86 return bless $class->SUPER::new(
27             not_null => q~NOT NULL~,
28             unique => q~UNIQUE~,
29             primary_key => q~PRIMARY KEY~,
30             foreign_key => q~FOREIGN KEY~,
31             check => q~CHECK~,
32             ),
33             $class;
34             }
35             }
36             {
37              
38             package Geoffrey::Converter::SQLite::View;
39              
40 19     19   2406 use parent 'Geoffrey::Role::ConverterType';
  19         49  
  19         126  
41              
42 3     3   17 sub add { return 'CREATE VIEW {0} AS {1}'; }
43              
44 3     3   15 sub drop { return 'DROP VIEW {0}'; }
45              
46             sub list {
47 4     4   12 my ( $self, $schema ) = @_;
48 4         19 require Geoffrey::Utils;
49             return
50 4         15 q~SELECT * FROM ~
51             . Geoffrey::Utils::add_schema($schema)
52             . q~sqlite_master WHERE type='view'~;
53             }
54             }
55             {
56              
57             package Geoffrey::Converter::SQLite::ForeignKey;
58 19     19   3271 use parent 'Geoffrey::Role::ConverterType';
  19         48  
  19         71  
59 19     19   159 sub add { return 'FOREIGN KEY ({0}) REFERENCES {1}({2})' }
60             }
61             {
62             package Geoffrey::Converter::SQLite::PrimaryKey;
63 19     19   1984 use parent 'Geoffrey::Role::ConverterType';
  19         52  
  19         105  
64 2     2   7 sub add { return 'CONSTRAINT {0} PRIMARY KEY ( {1} )'; }
65             }
66             {
67              
68             package Geoffrey::Converter::SQLite::UniqueIndex;
69 19     19   2014 use parent 'Geoffrey::Role::ConverterType';
  19         63  
  19         130  
70 3     3   8 sub append { return 'CREATE UNIQUE INDEX IF NOT EXISTS {0} ON {1} ( {2} )'; }
71 2     2   8 sub add { return 'CONSTRAINT {0} UNIQUE ( {1} )'; }
72 1     1   7 sub drop { return 'DROP INDEX IF EXISTS {1}'; }
73             }
74             {
75              
76             package Geoffrey::Converter::SQLite::Trigger;
77 19     19   2506 use parent 'Geoffrey::Role::ConverterType';
  19         53  
  19         161  
78              
79             sub add {
80 17     17   37 my ( $self, $options ) = @_;
81 17         29 my $s_sql_standard = <<'EOF';
82             CREATE TRIGGER {0} UPDATE OF {1} ON {2}
83             BEGIN
84             {4}
85             END
86             EOF
87 17         25 my $s_sql_view = <<'EOF';
88             CREATE TRIGGER {0} INSTEAD OF UPDATE OF {1} ON {2}
89             BEGIN
90             {4}
91             END
92             EOF
93 17 100       103 return $options->{for_view} ? $s_sql_view : $s_sql_standard;
94             }
95              
96 6     6   25 sub drop { return 'DROP TRIGGER IF EXISTS {1}'; }
97             }
98              
99             sub new {
100 24     24 1 165371 my $class = shift;
101 24         297 my $self = $class->SUPER::new(@_);
102 24         149 $self->{min_version} = '3.7';
103 24         104 return bless $self, $class;
104             }
105              
106             sub defaults {
107             return {
108 49     49 1 165 current_timestamp => 'CURRENT_TIMESTAMP',
109             autoincrement => 'AUTOINCREMENT',
110             };
111             }
112              
113             sub types {
114             return {
115 82     82 1 762 blob => 'BLOB',
116             integer => 'INTEGER',
117             numeric => 'NUMERIC',
118             real => 'REAL',
119             text => 'TEXT',
120             bool => 'BOOL',
121             double => 'DOUBLE',
122             float => 'FLOAT',
123             char => 'CHAR',
124             varchar => 'VARCHAR',
125             timestamp => 'DATETIME',
126             };
127             }
128              
129             sub select_get_table {
130             return
131 3     3 1 10 q~SELECT t.name AS table_name FROM sqlite_master t WHERE type='table' AND t.name = ?~;
132             }
133              
134             sub convert_defaults {
135 30     30 1 58 my ( $self, $params ) = @_;
136 30         217 return $params->{default};
137             }
138 1     1 1 5 sub can_create_empty_table { return 0 }
139              
140             sub colums_information {
141 2     2 1 664 my ( $self, $ar_raw_data ) = @_;
142 2 50       6 return [] if scalar @{$ar_raw_data} == 0;
  2         9  
143 2         5 my $table_row = shift @{$ar_raw_data};
  2         5  
144 2         61 $table_row->{sql} =~ s/^.*(CREATE|create) (.*)\(/$2/g;
145 2         8 my $columns = [];
146 2         14 for ( split m/,/, $table_row->{sql} ) {
147 22         50 s/^TABLE\s+\S+\s+\((.*)/$1/g;
148 22         112 s/^\s*(.*)\s*$/$1/g;
149 22         45 my $rx_not_null = 'NOT NULL';
150 22         62 my $rx_primary_key = 'PRIMARY KEY';
151 22         31 my $rx_default = 'AUTOINCREMENT|DEFAULT';
152 22         199 my $rx_column_values = qr/($rx_not_null)*\s($rx_primary_key)*.*($rx_default \w{1,})*/;
153 22         298 my @column = m/^(\w+)\s([[:upper:]]+)(\(\d*\))*\s$rx_column_values$/;
154 22 100       85 next if scalar @column == 0;
155 17 100       62 $column[$I_CONST_LENGTH_VALUE] =~ s/([\(\)])//g if $column[$I_CONST_LENGTH_VALUE];
156 17 100       26 push @{$columns},
  17 100       124  
    100          
    50          
157             {
158             name => $column[0],
159             type => $column[1],
160             (
161             $column[$I_CONST_LENGTH_VALUE] ? ( length => $column[$I_CONST_LENGTH_VALUE] )
162             : ()
163             ),
164             (
165             $column[$I_CONST_NOT_NULL_VALUE]
166             ? ( not_null => $column[$I_CONST_NOT_NULL_VALUE] )
167             : ()
168             ),
169             (
170             $column[$I_CONST_PRIMARY_KEY_VALUE]
171             ? ( primary_key => $column[$I_CONST_PRIMARY_KEY_VALUE] )
172             : ()
173             ),
174             (
175             $column[$I_CONST_DEFAULT_VALUE]
176             ? ( default => $column[$I_CONST_DEFAULT_VALUE] )
177             : ()
178             ),
179             };
180             }
181 2         28 return $columns;
182             }
183              
184             sub index_information {
185 3     3 1 1149 my ( $self, $ar_raw_data ) = @_;
186 3         8 my @mapped = ();
187 3         7 for ( @{$ar_raw_data} ) {
  3         12  
188 6 100       22 next if !$_->{sql};
189 3         40 my ($s_columns) = $_->{sql} =~ m/\((.*)\)$/;
190 3         16 my @columns = split m/,/, $s_columns;
191 3         20 s/^\s+|\s+$//g for @columns;
192             push @mapped,
193             {
194             name => $_->{name},
195             table => $_->{tbl_name},
196 3         19 columns => \@columns
197             };
198             }
199 3         28 return \@mapped;
200             }
201              
202             sub view_information {
203 3     3 1 860 my ( $self, $ar_raw_data ) = @_;
204 3 50       13 return [] unless $ar_raw_data;
205 3         8 return [ map { { name => $_->{name}, sql => $_->{sql} } } @{$ar_raw_data} ];
  3         21  
  3         14  
206             }
207              
208             sub constraints {
209 79     79 1 224 my ($self) = @_;
210 79   66     208 $self->{constraints} //= Geoffrey::Converter::SQLite::Constraints->new;
211 79         170 return $self->{constraints};
212             }
213              
214             sub index {
215 20     20 1 4168 my ( $self, $new_value ) = @_;
216 20         3313 require Geoffrey::Converter::SQLite::Index;
217 20 100       84 $self->{index} = $new_value if defined $new_value;
218 20   66     153 $self->{index} //= Geoffrey::Converter::SQLite::Index->new;
219 20         93 return $self->{index};
220             }
221              
222             sub table {
223 28     28 1 75 my ($self) = @_;
224 28         2786 require Geoffrey::Converter::SQLite::Tables;
225 28   66     179 $self->{table} //= Geoffrey::Converter::SQLite::Tables->new;
226 28         113 return $self->{table};
227             }
228              
229             sub view {
230 9     9 1 25 my ($self) = @_;
231 9   66     97 $self->{view} //= Geoffrey::Converter::SQLite::View->new;
232 9         42 return $self->{view};
233             }
234              
235             sub foreign_key {
236 80     80 1 4046 my ( $self, $new_value ) = @_;
237 80 100       196 $self->{foreign_key} = $new_value if defined $new_value;
238 80   66     372 $self->{foreign_key} //= Geoffrey::Converter::SQLite::ForeignKey->new;
239 80         284 return $self->{foreign_key};
240             }
241              
242             sub trigger {
243 33     33 1 82 my ( $self, $o_trigger ) = @_;
244 33 100       94 $self->{trigger} = $o_trigger if defined $o_trigger;
245 33   66     140 $self->{trigger} //= Geoffrey::Converter::SQLite::Trigger->new;
246 33         72 return $self->{trigger};
247             }
248              
249             sub primary_key {
250 15     15 1 30 my ($self) = @_;
251 15   66     93 $self->{primary_key} //= Geoffrey::Converter::SQLite::PrimaryKey->new;
252 15         87 return $self->{primary_key};
253             }
254              
255             sub unique {
256 19     19 1 40 my ($self) = @_;
257 19   66     98 $self->{unique} //= Geoffrey::Converter::SQLite::UniqueIndex->new;
258 19         43 return $self->{unique};
259             }
260              
261             1; # End of Geoffrey::Converter::SQLite
262              
263             __END__