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   583946 use utf8;
  19         200  
  19         116  
4 19     19   834 use 5.016;
  19         71  
5 19     19   128 use strict;
  19         38  
  19         541  
6 19     19   7419 use Readonly;
  19         56174  
  19         1037  
7 19     19   134 use warnings;
  19         41  
  19         920  
8              
9             $Geoffrey::Converter::SQLite::VERSION = '0.000204';
10              
11 19     19   3671 use parent 'Geoffrey::Role::Converter';
  19         2250  
  19         121  
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   1946 use parent 'Geoffrey::Role::ConverterType';
  19         49  
  19         132  
23              
24             sub new {
25 4     4   12 my $class = shift;
26 4         46 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   2372 use parent 'Geoffrey::Role::ConverterType';
  19         47  
  19         127  
41              
42 3     3   18 sub add { return 'CREATE VIEW {0} AS {1}'; }
43              
44 3     3   17 sub drop { return 'DROP VIEW {0}'; }
45              
46             sub list {
47 4     4   12 my ( $self, $schema ) = @_;
48 4         26 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   3841 use parent 'Geoffrey::Role::ConverterType';
  19         41  
  19         83  
59 19     19   156 sub add { return 'FOREIGN KEY ({0}) REFERENCES {1}({2})' }
60             }
61             {
62             package Geoffrey::Converter::SQLite::PrimaryKey;
63 19     19   2100 use parent 'Geoffrey::Role::ConverterType';
  19         47  
  19         87  
64 2     2   8 sub add { return 'CONSTRAINT {0} PRIMARY KEY ( {1} )'; }
65             }
66             {
67              
68             package Geoffrey::Converter::SQLite::UniqueIndex;
69 19     19   2020 use parent 'Geoffrey::Role::ConverterType';
  19         67  
  19         101  
70 3     3   9 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   9 sub drop { return 'DROP INDEX IF EXISTS {1}'; }
73             }
74             {
75              
76             package Geoffrey::Converter::SQLite::Trigger;
77 19     19   2487 use parent 'Geoffrey::Role::ConverterType';
  19         73  
  19         123  
78              
79             sub add {
80 17     17   33 my ( $self, $options ) = @_;
81 17         27 my $s_sql_standard = <<'EOF';
82             CREATE TRIGGER {0} UPDATE OF {1} ON {2}
83             BEGIN
84             {4}
85             END
86             EOF
87 17         23 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 173027 my $class = shift;
101 24         293 my $self = $class->SUPER::new(@_);
102 24         126 $self->{min_version} = '3.7';
103 24         96 return bless $self, $class;
104             }
105              
106             sub defaults {
107             return {
108 49     49 1 169 current_timestamp => 'CURRENT_TIMESTAMP',
109             autoincrement => 'AUTOINCREMENT',
110             };
111             }
112              
113             sub types {
114             return {
115 82     82 1 773 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 9 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 56 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 762 my ( $self, $ar_raw_data ) = @_;
142 2 50       5 return [] if scalar @{$ar_raw_data} == 0;
  2         12  
143 2         4 my $table_row = shift @{$ar_raw_data};
  2         6  
144 2         54 $table_row->{sql} =~ s/^.*(CREATE|create) (.*)\(/$2/g;
145 2         7 my $columns = [];
146 2         17 for ( split m/,/, $table_row->{sql} ) {
147 22         47 s/^TABLE\s+\S+\s+\((.*)/$1/g;
148 22         96 s/^\s*(.*)\s*$/$1/g;
149 22         43 my $rx_not_null = 'NOT NULL';
150 22         32 my $rx_primary_key = 'PRIMARY KEY';
151 22         27 my $rx_default = 'AUTOINCREMENT|DEFAULT';
152 22         234 my $rx_column_values = qr/($rx_not_null)*\s($rx_primary_key)*.*($rx_default \w{1,})*/;
153 22         316 my @column = m/^(\w+)\s([[:upper:]]+)(\(\d*\))*\s$rx_column_values$/;
154 22 100       83 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       28 push @{$columns},
  17 100       121  
    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         37 return $columns;
182             }
183              
184             sub index_information {
185 3     3 1 1226 my ( $self, $ar_raw_data ) = @_;
186 3         10 my @mapped = ();
187 3         7 for ( @{$ar_raw_data} ) {
  3         13  
188 6 100       21 next if !$_->{sql};
189 3         34 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         37 return \@mapped;
200             }
201              
202             sub view_information {
203 3     3 1 940 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         23  
  3         13  
206             }
207              
208             sub constraints {
209 79     79 1 141 my ($self) = @_;
210 79   66     224 $self->{constraints} //= Geoffrey::Converter::SQLite::Constraints->new;
211 79         188 return $self->{constraints};
212             }
213              
214             sub index {
215 20     20 1 3885 my ( $self, $new_value ) = @_;
216 20         2993 require Geoffrey::Converter::SQLite::Index;
217 20 100       97 $self->{index} = $new_value if defined $new_value;
218 20   66     153 $self->{index} //= Geoffrey::Converter::SQLite::Index->new;
219 20         99 return $self->{index};
220             }
221              
222             sub table {
223 28     28 1 77 my ($self) = @_;
224 28         3012 require Geoffrey::Converter::SQLite::Tables;
225 28   66     192 $self->{table} //= Geoffrey::Converter::SQLite::Tables->new;
226 28         122 return $self->{table};
227             }
228              
229             sub view {
230 9     9 1 27 my ($self) = @_;
231 9   66     105 $self->{view} //= Geoffrey::Converter::SQLite::View->new;
232 9         43 return $self->{view};
233             }
234              
235             sub foreign_key {
236 80     80 1 4268 my ( $self, $new_value ) = @_;
237 80 100       215 $self->{foreign_key} = $new_value if defined $new_value;
238 80   66     544 $self->{foreign_key} //= Geoffrey::Converter::SQLite::ForeignKey->new;
239 80         300 return $self->{foreign_key};
240             }
241              
242             sub trigger {
243 33     33 1 71 my ( $self, $o_trigger ) = @_;
244 33 100       90 $self->{trigger} = $o_trigger if defined $o_trigger;
245 33   66     132 $self->{trigger} //= Geoffrey::Converter::SQLite::Trigger->new;
246 33         73 return $self->{trigger};
247             }
248              
249             sub primary_key {
250 15     15 1 33 my ($self) = @_;
251 15   66     95 $self->{primary_key} //= Geoffrey::Converter::SQLite::PrimaryKey->new;
252 15         89 return $self->{primary_key};
253             }
254              
255             sub unique {
256 19     19 1 48 my ($self) = @_;
257 19   66     99 $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__