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   580083 use utf8;
  19         192  
  19         115  
4 19     19   774 use 5.016;
  19         67  
5 19     19   123 use strict;
  19         40  
  19         426  
6 19     19   7435 use Readonly;
  19         55058  
  19         1012  
7 19     19   146 use warnings;
  19         39  
  19         898  
8              
9             $Geoffrey::Converter::SQLite::VERSION = '0.000205';
10              
11 19     19   3644 use parent 'Geoffrey::Role::Converter';
  19         2317  
  19         110  
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   2045 use parent 'Geoffrey::Role::ConverterType';
  19         38  
  19         127  
23              
24             sub new {
25 4     4   9 my $class = shift;
26 4         42 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   2342 use parent 'Geoffrey::Role::ConverterType';
  19         46  
  19         110  
41              
42 3     3   16 sub add { return 'CREATE VIEW {0} AS {1}'; }
43              
44 3     3   16 sub drop { return 'DROP VIEW {0}'; }
45              
46             sub list {
47 4     4   14 my ( $self, $schema ) = @_;
48 4         23 require Geoffrey::Utils;
49             return
50 4         18 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   3308 use parent 'Geoffrey::Role::ConverterType';
  19         43  
  19         84  
59 19     19   142 sub add { return 'FOREIGN KEY ({0}) REFERENCES {1}({2})' }
60             }
61             {
62             package Geoffrey::Converter::SQLite::PrimaryKey;
63 19     19   2094 use parent 'Geoffrey::Role::ConverterType';
  19         55  
  19         90  
64 2     2   6 sub add { return 'CONSTRAINT {0} PRIMARY KEY ( {1} )'; }
65             }
66             {
67              
68             package Geoffrey::Converter::SQLite::UniqueIndex;
69 19     19   2286 use parent 'Geoffrey::Role::ConverterType';
  19         53  
  19         84  
70 3     3   10 sub append { return 'CREATE UNIQUE INDEX IF NOT EXISTS {0} ON {1} ( {2} )'; }
71 2     2   10 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   2571 use parent 'Geoffrey::Role::ConverterType';
  19         79  
  19         144  
78              
79             sub add {
80 17     17   79 my ( $self, $options ) = @_;
81 17         28 my $s_sql_standard = <<'EOF';
82             CREATE TRIGGER {0} UPDATE OF {1} ON {2}
83             BEGIN
84             {4}
85             END
86             EOF
87 17         20 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       107 return $options->{for_view} ? $s_sql_view : $s_sql_standard;
94             }
95              
96 6     6   24 sub drop { return 'DROP TRIGGER IF EXISTS {1}'; }
97             }
98              
99             sub new {
100 24     24 1 168181 my $class = shift;
101 24         229 my $self = $class->SUPER::new(@_);
102 24         123 $self->{min_version} = '3.7';
103 24         98 return bless $self, $class;
104             }
105              
106             sub defaults {
107             return {
108 49     49 1 147 current_timestamp => 'CURRENT_TIMESTAMP',
109             autoincrement => 'AUTOINCREMENT',
110             };
111             }
112              
113             sub types {
114             return {
115 82     82 1 725 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 7 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 53 my ( $self, $params ) = @_;
136 30         216 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 673 my ( $self, $ar_raw_data ) = @_;
142 2 50       5 return [] if scalar @{$ar_raw_data} == 0;
  2         11  
143 2         5 my $table_row = shift @{$ar_raw_data};
  2         6  
144 2         53 $table_row->{sql} =~ s/^.*(CREATE|create) (.*)\(/$2/g;
145 2         6 my $columns = [];
146 2         18 for ( split m/,/, $table_row->{sql} ) {
147 22         48 s/^TABLE\s+\S+\s+\((.*)/$1/g;
148 22         98 s/^\s*(.*)\s*$/$1/g;
149 22         42 my $rx_not_null = 'NOT NULL';
150 22         31 my $rx_primary_key = 'PRIMARY KEY';
151 22         30 my $rx_default = 'AUTOINCREMENT|DEFAULT';
152 22         216 my $rx_column_values = qr/($rx_not_null)*\s($rx_primary_key)*.*($rx_default \w{1,})*/;
153 22         368 my @column = m/^(\w+)\s([[:upper:]]+)(\(\d*\))*\s$rx_column_values$/;
154 22 100       64 next if scalar @column == 0;
155 17 100       64 $column[$I_CONST_LENGTH_VALUE] =~ s/([\(\)])//g if $column[$I_CONST_LENGTH_VALUE];
156 17 100       27 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 953 my ( $self, $ar_raw_data ) = @_;
186 3         9 my @mapped = ();
187 3         6 for ( @{$ar_raw_data} ) {
  3         10  
188 6 100       22 next if !$_->{sql};
189 3         23 my ($s_columns) = $_->{sql} =~ m/\((.*)\)$/;
190 3         16 my @columns = split m/,/, $s_columns;
191 3         18 s/^\s+|\s+$//g for @columns;
192             push @mapped,
193             {
194             name => $_->{name},
195             table => $_->{tbl_name},
196 3         16 columns => \@columns
197             };
198             }
199 3         20 return \@mapped;
200             }
201              
202             sub view_information {
203 3     3 1 865 my ( $self, $ar_raw_data ) = @_;
204 3 50       11 return [] unless $ar_raw_data;
205 3         9 return [ map { { name => $_->{name}, sql => $_->{sql} } } @{$ar_raw_data} ];
  3         25  
  3         12  
206             }
207              
208             sub constraints {
209 79     79 1 150 my ($self) = @_;
210 79   66     196 $self->{constraints} //= Geoffrey::Converter::SQLite::Constraints->new;
211 79         157 return $self->{constraints};
212             }
213              
214             sub index {
215 20     20 1 3646 my ( $self, $new_value ) = @_;
216 20         2788 require Geoffrey::Converter::SQLite::Index;
217 20 100       82 $self->{index} = $new_value if defined $new_value;
218 20   66     124 $self->{index} //= Geoffrey::Converter::SQLite::Index->new;
219 20         82 return $self->{index};
220             }
221              
222             sub table {
223 28     28 1 103 my ($self) = @_;
224 28         2684 require Geoffrey::Converter::SQLite::Tables;
225 28   66     171 $self->{table} //= Geoffrey::Converter::SQLite::Tables->new;
226 28         108 return $self->{table};
227             }
228              
229             sub view {
230 9     9 1 25 my ($self) = @_;
231 9   66     92 $self->{view} //= Geoffrey::Converter::SQLite::View->new;
232 9         40 return $self->{view};
233             }
234              
235             sub foreign_key {
236 80     80 1 3938 my ( $self, $new_value ) = @_;
237 80 100       204 $self->{foreign_key} = $new_value if defined $new_value;
238 80   66     329 $self->{foreign_key} //= Geoffrey::Converter::SQLite::ForeignKey->new;
239 80         302 return $self->{foreign_key};
240             }
241              
242             sub trigger {
243 33     33 1 66 my ( $self, $o_trigger ) = @_;
244 33 100       91 $self->{trigger} = $o_trigger if defined $o_trigger;
245 33   66     135 $self->{trigger} //= Geoffrey::Converter::SQLite::Trigger->new;
246 33         68 return $self->{trigger};
247             }
248              
249             sub primary_key {
250 15     15 1 30 my ($self) = @_;
251 15   66     169 $self->{primary_key} //= Geoffrey::Converter::SQLite::PrimaryKey->new;
252 15         86 return $self->{primary_key};
253             }
254              
255             sub unique {
256 19     19 1 40 my ($self) = @_;
257 19   66     92 $self->{unique} //= Geoffrey::Converter::SQLite::UniqueIndex->new;
258 19         50 return $self->{unique};
259             }
260              
261             1; # End of Geoffrey::Converter::SQLite
262              
263             __END__