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   2015665 use utf8;
  19         1954  
  19         122  
4 19     19   984 use 5.016;
  19         129  
5 19     19   129 use strict;
  19         32  
  19         439  
6 19     19   7492 use Readonly;
  19         66034  
  19         1258  
7 19     19   296 use warnings;
  19         73  
  19         1537  
8              
9             $Geoffrey::Converter::SQLite::VERSION = '0.000206';
10              
11 19     19   2799 use parent 'Geoffrey::Role::Converter';
  19         1896  
  19         166  
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   2167 use parent 'Geoffrey::Role::ConverterType';
  19         37  
  19         99  
23              
24             sub new {
25 4     4   10 my $class = shift;
26 4         47 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   2873 use parent 'Geoffrey::Role::ConverterType';
  19         36  
  19         160  
41              
42 3     3   17 sub add { return 'CREATE VIEW {0} AS {1}'; }
43              
44 3     3   19 sub drop { return 'DROP VIEW {0}'; }
45              
46             sub list {
47 4     4   11 my ( $self, $schema ) = @_;
48 4         30 require Geoffrey::Utils;
49             return
50 4         19 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   4147 use parent 'Geoffrey::Role::ConverterType';
  19         43  
  19         103  
59 19     19   213 sub add { return 'FOREIGN KEY ({0}) REFERENCES {1}({2})' }
60             }
61             {
62             package Geoffrey::Converter::SQLite::PrimaryKey;
63 19     19   2443 use parent 'Geoffrey::Role::ConverterType';
  19         56  
  19         101  
64 2     2   7 sub add { return 'CONSTRAINT {0} PRIMARY KEY ( {1} )'; }
65             }
66             {
67              
68             package Geoffrey::Converter::SQLite::UniqueIndex;
69 19     19   2240 use parent 'Geoffrey::Role::ConverterType';
  19         163  
  19         145  
70 3     3   12 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   5 sub drop { return 'DROP INDEX IF EXISTS {1}'; }
73             }
74             {
75              
76             package Geoffrey::Converter::SQLite::Trigger;
77 19     19   2924 use parent 'Geoffrey::Role::ConverterType';
  19         48  
  19         100  
78              
79             sub add {
80 17     17   22 my ( $self, $options ) = @_;
81 17         21 my $s_sql_standard = <<'EOF';
82             CREATE TRIGGER {0} UPDATE OF {1} ON {2}
83             BEGIN
84             {4}
85             END
86             EOF
87 17         17 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       113 return $options->{for_view} ? $s_sql_view : $s_sql_standard;
94             }
95              
96 6     6   23 sub drop { return 'DROP TRIGGER IF EXISTS {1}'; }
97             }
98              
99             sub new {
100 24     24 1 214414 my $class = shift;
101 24         345 my $self = $class->SUPER::new(@_);
102 24         1466 $self->{min_version} = '3.7';
103 24         149 return bless $self, $class;
104             }
105              
106             sub defaults {
107             return {
108 49     49 1 250 current_timestamp => 'CURRENT_TIMESTAMP',
109             autoincrement => 'AUTOINCREMENT',
110             };
111             }
112              
113             sub types {
114             return {
115 82     82 1 1294 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 62 my ( $self, $params ) = @_;
136 30         358 return $params->{default};
137             }
138 1     1 1 6 sub can_create_empty_table { return 0 }
139              
140             sub colums_information {
141 2     2 1 1029 my ( $self, $ar_raw_data ) = @_;
142 2 50       8 return [] if scalar @{$ar_raw_data} == 0;
  2         11  
143 2         6 my $table_row = shift @{$ar_raw_data};
  2         6  
144 2         61 $table_row->{sql} =~ s/^.*(CREATE|create) (.*)\(/$2/g;
145 2         9 my $columns = [];
146 2         14 for ( split m/,/, $table_row->{sql} ) {
147 22         56 s/^TABLE\s+\S+\s+\((.*)/$1/g;
148 22         100 s/^\s*(.*)\s*$/$1/g;
149 22         41 my $rx_not_null = 'NOT NULL';
150 22         35 my $rx_primary_key = 'PRIMARY KEY';
151 22         55 my $rx_default = 'AUTOINCREMENT|DEFAULT';
152 22         348 my $rx_column_values = qr/($rx_not_null)*\s($rx_primary_key)*.*($rx_default \w{1,})*/;
153 22         460 my @column = m/^(\w+)\s([[:upper:]]+)(\(\d*\))*\s$rx_column_values$/;
154 22 100       143 next if scalar @column == 0;
155 17 100       79 $column[$I_CONST_LENGTH_VALUE] =~ s/([\(\)])//g if $column[$I_CONST_LENGTH_VALUE];
156 17 100       47 push @{$columns},
  17 100       160  
    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         38 return $columns;
182             }
183              
184             sub index_information {
185 3     3 1 1228 my ( $self, $ar_raw_data ) = @_;
186 3         9 my @mapped = ();
187 3         7 for ( @{$ar_raw_data} ) {
  3         10  
188 6 100       21 next if !$_->{sql};
189 3         23 my ($s_columns) = $_->{sql} =~ m/\((.*)\)$/;
190 3         10 my @columns = split m/,/, $s_columns;
191 3         21 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         59 return \@mapped;
200             }
201              
202             sub view_information {
203 3     3 1 1144 my ( $self, $ar_raw_data ) = @_;
204 3 50       14 return [] unless $ar_raw_data;
205 3         9 return [ map { { name => $_->{name}, sql => $_->{sql} } } @{$ar_raw_data} ];
  3         28  
  3         16  
206             }
207              
208             sub constraints {
209 79     79 1 164 my ($self) = @_;
210 79   66     224 $self->{constraints} //= Geoffrey::Converter::SQLite::Constraints->new;
211 79         172 return $self->{constraints};
212             }
213              
214             sub index {
215 20     20 1 4858 my ( $self, $new_value ) = @_;
216 20         5154 require Geoffrey::Converter::SQLite::Index;
217 20 100       84 $self->{index} = $new_value if defined $new_value;
218 20   66     155 $self->{index} //= Geoffrey::Converter::SQLite::Index->new;
219 20         90 return $self->{index};
220             }
221              
222             sub table {
223 28     28 1 68 my ($self) = @_;
224 28         3957 require Geoffrey::Converter::SQLite::Tables;
225 28   66     170 $self->{table} //= Geoffrey::Converter::SQLite::Tables->new;
226 28         122 return $self->{table};
227             }
228              
229             sub view {
230 9     9 1 37 my ($self) = @_;
231 9   66     106 $self->{view} //= Geoffrey::Converter::SQLite::View->new;
232 9         39 return $self->{view};
233             }
234              
235             sub foreign_key {
236 80     80 1 6527 my ( $self, $new_value ) = @_;
237 80 100       264 $self->{foreign_key} = $new_value if defined $new_value;
238 80   66     407 $self->{foreign_key} //= Geoffrey::Converter::SQLite::ForeignKey->new;
239 80         411 return $self->{foreign_key};
240             }
241              
242             sub trigger {
243 33     33 1 54 my ( $self, $o_trigger ) = @_;
244 33 100       70 $self->{trigger} = $o_trigger if defined $o_trigger;
245 33   66     122 $self->{trigger} //= Geoffrey::Converter::SQLite::Trigger->new;
246 33         127 return $self->{trigger};
247             }
248              
249             sub primary_key {
250 15     15 1 29 my ($self) = @_;
251 15   66     97 $self->{primary_key} //= Geoffrey::Converter::SQLite::PrimaryKey->new;
252 15         78 return $self->{primary_key};
253             }
254              
255             sub unique {
256 19     19 1 44 my ($self) = @_;
257 19   66     110 $self->{unique} //= Geoffrey::Converter::SQLite::UniqueIndex->new;
258 19         54 return $self->{unique};
259             }
260              
261             1; # End of Geoffrey::Converter::SQLite
262              
263             __END__