File Coverage

blib/lib/DBD/SQLeet/VirtualTable.pm
Criterion Covered Total %
statement 67 93 72.0
branch 3 6 50.0
condition n/a
subroutine 24 37 64.8
pod 20 22 90.9
total 114 158 72.1


line stmt bran cond sub pod time code
1             #======================================================================
2             package DBD::SQLeet::VirtualTable;
3             #======================================================================
4 8     8   1789 use strict;
  8         15  
  8         188  
5 8     8   88 use warnings;
  8         16  
  8         204  
6 8     8   37 use Scalar::Util qw/weaken/;
  8         12  
  8         7246  
7              
8             our $VERSION = '1.58';
9             our @ISA;
10              
11              
12             #----------------------------------------------------------------------
13             # methods for registering/destroying the module
14             #----------------------------------------------------------------------
15              
16 11     11 1 4059 sub CREATE_MODULE { my ($class, $mod_name) = @_; }
17 8     8 1 1244 sub DESTROY_MODULE { my ($class, $mod_name) = @_; }
18              
19             #----------------------------------------------------------------------
20             # methods for creating/destroying instances
21             #----------------------------------------------------------------------
22              
23 13     13 1 68 sub CREATE { my $class = shift; return $class->NEW(@_); }
  13         117  
24 2     2 1 17 sub CONNECT { my $class = shift; return $class->NEW(@_); }
  2         11  
25              
26             sub _PREPARE_SELF {
27 15     15   75 my ($class, $dbh_ref, $module_name, $db_name, $vtab_name, @args) = @_;
28              
29 15         32 my @columns;
30             my %options;
31              
32             # args containing '=' are options; others are column declarations
33 15         38 foreach my $arg (@args) {
34 43 100       162 if ($arg =~ /^([^=\s]+)\s*=\s*(.*)/) {
35 15         54 my ($key, $val) = ($1, $2);
36 15         89 $val =~ s/^"(.*)"$/$1/;
37 15         54 $options{$key} = $val;
38             }
39             else {
40 28         4174 push @columns, $arg;
41             }
42             }
43              
44             # build $self
45 15         96 my $self = {
46             dbh_ref => $dbh_ref,
47             module_name => $module_name,
48             db_name => $db_name,
49             vtab_name => $vtab_name,
50             columns => \@columns,
51             options => \%options,
52             };
53 15         66 weaken $self->{dbh_ref};
54              
55 15         48 return $self;
56             }
57              
58             sub NEW {
59 5     5 1 12 my $class = shift;
60              
61 5         22 my $self = $class->_PREPARE_SELF(@_);
62 5         33 bless $self, $class;
63             }
64              
65              
66             sub VTAB_TO_DECLARE {
67 15     15 1 32 my $self = shift;
68              
69 15         26 local $" = ", ";
70 15         72 my $sql = "CREATE TABLE $self->{vtab_name}(@{$self->{columns}})";
  15         65  
71              
72 15         1195 return $sql;
73             }
74              
75 1     1 1 27 sub DROP { my $self = shift; }
76 11     11 1 7208 sub DISCONNECT { my $self = shift; }
77              
78              
79             #----------------------------------------------------------------------
80             # methods for initiating a search
81             #----------------------------------------------------------------------
82              
83             sub BEST_INDEX {
84 1     1 1 5 my ($self, $constraints, $order_by) = @_;
85              
86 1         2 my $ix = 0;
87 1         4 foreach my $constraint (grep {$_->{usable}} @$constraints) {
  0         0  
88 0         0 $constraint->{argvIndex} = $ix++;
89 0         0 $constraint->{omit} = 0;
90             }
91              
92             # stupid default values -- subclasses should put real values instead
93 1         5 my $outputs = {
94             idxNum => 1,
95             idxStr => "",
96             orderByConsumed => 0,
97             estimatedCost => 1.0,
98             estimatedRows => undef,
99             };
100              
101 1         22 return $outputs;
102             }
103              
104              
105             sub OPEN {
106 107     107   4166 my $self = shift;
107 107         209 my $class = ref $self;
108              
109 107         191 my $cursor_class = $class . "::Cursor";
110 107         487 return $cursor_class->NEW($self, @_);
111             }
112              
113              
114             #----------------------------------------------------------------------
115             # methods for insert/delete/update
116             #----------------------------------------------------------------------
117              
118             sub _SQLITE_UPDATE {
119 5     5   14 my ($self, $old_rowid, $new_rowid, @values) = @_;
120              
121 5 50       12 if (! defined $old_rowid) {
    0          
122 5         13 return $self->INSERT($new_rowid, @values);
123             }
124             elsif (!@values) {
125 0         0 return $self->DELETE($old_rowid);
126             }
127             else {
128 0         0 return $self->UPDATE($old_rowid, $new_rowid, @values);
129             }
130             }
131              
132             sub INSERT {
133 0     0 1 0 my ($self, $new_rowid, @values) = @_;
134              
135 0         0 die "INSERT() should be redefined in subclass";
136             }
137              
138             sub DELETE {
139 0     0   0 my ($self, $old_rowid) = @_;
140              
141 0         0 die "DELETE() should be redefined in subclass";
142             }
143              
144             sub UPDATE {
145 0     0 1 0 my ($self, $old_rowid, $new_rowid, @values) = @_;
146              
147 0         0 die "UPDATE() should be redefined in subclass";
148             }
149              
150             #----------------------------------------------------------------------
151             # remaining methods of the sqlite API
152             #----------------------------------------------------------------------
153              
154 3     3 1 20 sub BEGIN_TRANSACTION {return 0}
155 16     16 1 142386 sub SYNC_TRANSACTION {return 0}
156 16     16 0 238 sub COMMIT_TRANSACTION {return 0}
157 0     0 1 0 sub ROLLBACK_TRANSACTION {return 0}
158 0     0 1 0 sub SAVEPOINT {return 0}
159 0     0 1 0 sub RELEASE {return 0}
160 0     0 1 0 sub ROLLBACK_TO {return 0}
161 1     1 1 17 sub FIND_FUNCTION {return 0}
162 0     0 1 0 sub RENAME {return 0}
163              
164              
165             #----------------------------------------------------------------------
166             # utility methods
167             #----------------------------------------------------------------------
168              
169             sub dbh {
170 64     64 1 96 my $self = shift;
171 64         78 return ${$self->{dbh_ref}};
  64         236  
172             }
173              
174              
175             sub sqlite_table_info {
176 9     9 0 16 my $self = shift;
177              
178 9         34 my $sql = "PRAGMA table_info($self->{vtab_name})";
179 9         35 return $self->dbh->selectall_arrayref($sql, {Slice => {}});
180             }
181              
182             #======================================================================
183             package DBD::SQLeet::VirtualTable::Cursor;
184             #======================================================================
185 8     8   89 use strict;
  8         16  
  8         169  
186 8     8   43 use warnings;
  8         13  
  8         1543  
187              
188             sub NEW {
189 107     107   228 my ($class, $vtable, @args) = @_;
190 107         283 my $self = {vtable => $vtable,
191             args => \@args};
192 107         751 bless $self, $class;
193             }
194              
195              
196             sub FILTER {
197 0     0     my ($self, $idxNum, $idxStr, @values) = @_;
198 0           die "FILTER() should be redefined in cursor subclass";
199             }
200              
201             sub EOF {
202 0     0     my ($self) = @_;
203 0           die "EOF() should be redefined in cursor subclass";
204             }
205              
206             sub NEXT {
207 0     0     my ($self) = @_;
208 0           die "NEXT() should be redefined in cursor subclass";
209             }
210              
211             sub COLUMN {
212 0     0     my ($self, $idxCol) = @_;
213 0           die "COLUMN() should be redefined in cursor subclass";
214             }
215              
216             sub ROWID {
217 0     0     my ($self) = @_;
218 0           die "ROWID() should be redefined in cursor subclass";
219             }
220              
221              
222             1;
223              
224             __END__