File Coverage

blib/lib/DBD/Mem.pm
Criterion Covered Total %
statement 92 109 84.4
branch 12 24 50.0
condition 3 11 27.2
subroutine 24 27 88.8
pod 0 1 0.0
total 131 172 76.1


line stmt bran cond sub pod time code
1             # -*- perl -*-
2             #
3             # DBD::Mem - A DBI driver for in-memory tables
4             #
5             # This module is currently maintained by
6             #
7             # Jens Rehsack
8             #
9             # Copyright (C) 2016,2017 by Jens Rehsack
10             #
11             # All rights reserved.
12             #
13             # You may distribute this module under the terms of either the GNU
14             # General Public License or the Artistic License, as specified in
15             # the Perl README file.
16              
17             require 5.008;
18 2     2   2467 use strict;
  2         5  
  2         77  
19              
20             #################
21             package DBD::Mem;
22             #################
23 2     2   9 use base qw( DBI::DBD::SqlEngine );
  2         4  
  2         1154  
24 2     2   13 use vars qw($VERSION $ATTRIBUTION $drh);
  2         5  
  2         299  
25             $VERSION = '0.001';
26             $ATTRIBUTION = 'DBD::Mem by Jens Rehsack';
27              
28             # no need to have driver() unless you need private methods
29             #
30             sub driver ($;$)
31             {
32 2     2 0 6 my ( $class, $attr ) = @_;
33 2 50       6 return $drh if ($drh);
34              
35             # do the real work in DBI::DBD::SqlEngine
36             #
37 2         5 $attr->{Attribution} = 'DBD::Mem by Jens Rehsack';
38 2         13 $drh = $class->SUPER::driver($attr);
39              
40 2         8 return $drh;
41             }
42              
43             sub CLONE
44             {
45 0     0   0 undef $drh;
46             }
47              
48             #####################
49             package DBD::Mem::dr;
50             #####################
51             $DBD::Mem::dr::imp_data_size = 0;
52             @DBD::Mem::dr::ISA = qw(DBI::DBD::SqlEngine::dr);
53              
54             # you could put some :dr private methods here
55              
56             # you may need to over-ride some DBI::DBD::SqlEngine::dr methods here
57             # but you can probably get away with just letting it do the work
58             # in most cases
59              
60             #####################
61             package DBD::Mem::db;
62             #####################
63             $DBD::Mem::db::imp_data_size = 0;
64             @DBD::Mem::db::ISA = qw(DBI::DBD::SqlEngine::db);
65              
66 2     2   12 use Carp qw/carp/;
  2         4  
  2         491  
67              
68             sub set_versions
69             {
70 2     2   17 my $this = $_[0];
71 2         3 $this->{mem_version} = $DBD::Mem::VERSION;
72 2         13 return $this->SUPER::set_versions();
73             }
74              
75             sub init_valid_attributes
76             {
77 2     2   16 my $dbh = shift;
78              
79             # define valid private attributes
80             #
81             # attempts to set non-valid attrs in connect() or
82             # with $dbh->{attr} will throw errors
83             #
84             # the attrs here *must* start with mem_ or foo_
85             #
86             # see the STORE methods below for how to check these attrs
87             #
88             $dbh->{mem_valid_attrs} = {
89 2         10 mem_version => 1, # verbose DBD::Mem version
90             mem_valid_attrs => 1, # DBD::Mem::db valid attrs
91             mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs
92             mem_meta => 1, # DBD::Mem public access for f_meta
93             mem_tables => 1, # DBD::Mem public access for f_meta
94             };
95             $dbh->{mem_readonly_attrs} = {
96 2         7 mem_version => 1, # verbose DBD::Mem version
97             mem_valid_attrs => 1, # DBD::Mem::db valid attrs
98             mem_readonly_attrs => 1, # DBD::Mem::db r/o attrs
99             mem_meta => 1, # DBD::Mem public access for f_meta
100             };
101              
102 2         4 $dbh->{mem_meta} = "mem_tables";
103              
104 2         11 return $dbh->SUPER::init_valid_attributes();
105             }
106              
107             sub get_mem_versions
108             {
109 0     0   0 my ( $dbh, $table ) = @_;
110 0   0     0 $table ||= '';
111              
112 0         0 my $meta;
113 0         0 my $class = $dbh->{ImplementorClass};
114 0         0 $class =~ s/::db$/::Table/;
115 0 0       0 $table and ( undef, $meta ) = $class->get_table_meta( $dbh, $table, 1 );
116 0 0 0     0 $meta or ( $meta = {} and $class->bootstrap_table_meta( $dbh, $meta, $table ) );
117              
118 0         0 return sprintf( "%s using %s", $dbh->{mem_version}, $AnyData2::VERSION );
119             }
120              
121             package DBD::Mem::st;
122              
123 2     2   14 use strict;
  2         9  
  2         63  
124 2     2   24 use warnings;
  2         4  
  2         423  
125              
126             our $imp_data_size = 0;
127             our @ISA = qw(DBI::DBD::SqlEngine::st);
128              
129             ############################
130             package DBD::Mem::Statement;
131             ############################
132              
133             @DBD::Mem::Statement::ISA = qw(DBI::DBD::SqlEngine::Statement);
134              
135              
136             sub open_table ($$$$$)
137             {
138 18     18   35 my ( $self, $data, $table, $createMode, $lockMode ) = @_;
139              
140 18         32 my $class = ref $self;
141 18         64 $class =~ s/::Statement/::Table/;
142              
143 18         52 my $flags = {
144             createMode => $createMode,
145             lockMode => $lockMode,
146             };
147 18 0 33     65 if( defined( $data->{Database}->{mem_table_data}->{$table} ) && $data->{Database}->{mem_table_data}->{$table})
148             {
149 0         0 my $t = $data->{Database}->{mem_tables}->{$table};
150 0         0 $t->seek( $data, 0, 0 );
151 0         0 return $t;
152             }
153              
154 18         64 return $self->SUPER::open_table($data, $table, $createMode, $lockMode);
155             }
156              
157             # ====== DataSource ============================================================
158              
159             package DBD::Mem::DataSource;
160              
161 2     2   12 use strict;
  2         4  
  2         49  
162 2     2   10 use warnings;
  2         4  
  2         50  
163              
164 2     2   10 use Carp;
  2         3  
  2         276  
165              
166             @DBD::Mem::DataSource::ISA = "DBI::DBD::SqlEngine::DataSource";
167              
168             sub complete_table_name ($$;$)
169             {
170 4     4   17 my ( $self, $meta, $table, $respect_case ) = @_;
171 4         14 $table;
172             }
173              
174             sub open_data ($)
175             {
176 18     18   39 my ( $self, $meta, $attrs, $flags ) = @_;
177 18 100       51 defined $meta->{data_tbl} or $meta->{data_tbl} = [];
178             }
179              
180             ########################
181             package DBD::Mem::Table;
182             ########################
183              
184             # shamelessly stolen from SQL::Statement::RAM
185              
186 2     2   14 use Carp qw/croak/;
  2         3  
  2         95  
187              
188             @DBD::Mem::Table::ISA = qw(DBI::DBD::SqlEngine::Table);
189              
190 2     2   24 use Carp qw(croak);
  2         7  
  2         1081  
191              
192             sub new
193             {
194             #my ( $class, $tname, $col_names, $data_tbl ) = @_;
195 18     18   39 my ( $class, $data, $attrs, $flags ) = @_;
196 18         55 my $self = $class->SUPER::new($data, $attrs, $flags);
197              
198 18         35 my $meta = $self->{meta};
199 18         29 $self->{records} = $meta->{data_tbl};
200 18         32 $self->{index} = 0;
201              
202 18         84 $self;
203             }
204              
205             sub bootstrap_table_meta
206             {
207 4     4   18 my ( $self, $dbh, $meta, $table ) = @_;
208              
209 4 50       14 defined $meta->{sql_data_source} or $meta->{sql_data_source} = "DBD::Mem::DataSource";
210              
211 4         9 $meta;
212             }
213              
214             sub fetch_row
215             {
216 20     20   33 my ( $self, $data ) = @_;
217              
218             return $self->{row} =
219             ( $self->{records} and ( $self->{index} < scalar( @{ $self->{records} } ) ) )
220 20 100 66     42 ? [ @{ $self->{records}->[ $self->{index}++ ] } ]
  12         55  
221             : undef;
222             }
223              
224             sub push_row
225             {
226 12     12   23 my ( $self, $data, $fields ) = @_;
227 12         19 my $currentRow = $self->{index};
228 12         22 $self->{index} = $currentRow + 1;
229 12         22 $self->{records}->[$currentRow] = $fields;
230 12         23 return 1;
231             }
232              
233             sub truncate
234             {
235 6     6   10 my $self = shift;
236 6         10 return splice @{ $self->{records} }, $self->{index}, 1;
  6         16  
237             }
238              
239             sub push_names
240             {
241 4     4   12 my ( $self, $data, $names ) = @_;
242 4         8 my $meta = $self->{meta};
243 4         11 $meta->{col_names} = $self->{col_names} = $names;
244 4         7 $self->{org_col_names} = [ @{$names} ];
  4         13  
245 4         11 $self->{col_nums} = {};
246 4         27 $self->{col_nums}{ $names->[$_] } = $_ for ( 0 .. scalar @$names - 1 );
247             }
248              
249             sub drop ($)
250             {
251 0     0   0 my ($self, $data) = @_;
252 0         0 delete $data->{Database}{sql_meta}{$self->{table}};
253 0         0 return 1;
254             } # drop
255              
256             sub seek
257             {
258 12     12   29 my ( $self, $data, $pos, $whence ) = @_;
259 12 50       29 return unless defined $self->{records};
260              
261 12         21 my ($currentRow) = $self->{index};
262 12 100       48 if ( $whence == 0 )
    50          
    50          
263             {
264 6         8 $currentRow = $pos;
265             }
266             elsif ( $whence == 1 )
267             {
268 0         0 $currentRow += $pos;
269             }
270             elsif ( $whence == 2 )
271             {
272 6         9 $currentRow = @{ $self->{records} } + $pos;
  6         10  
273             }
274             else
275             {
276 0         0 croak $self . "->seek: Illegal whence argument ($whence)";
277             }
278              
279 12 50       25 $currentRow < 0 and
280             croak "Illegal row number: $currentRow";
281 12         27 $self->{index} = $currentRow;
282             }
283              
284             1;
285              
286             =head1 NAME
287              
288             DBD::Mem - a DBI driver for Mem & MLMem files
289              
290             =head1 SYNOPSIS
291              
292             use DBI;
293             $dbh = DBI->connect('dbi:Mem:', undef, undef, {});
294             $dbh = DBI->connect('dbi:Mem:', undef, undef, {RaiseError => 1});
295              
296             # or
297             $dbh = DBI->connect('dbi:Mem:');
298             $dbh = DBI->connect('DBI:Mem(RaiseError=1):');
299              
300             and other variations on connect() as shown in the L docs and
301             .
302              
303             Use standard DBI prepare, execute, fetch, placeholders, etc.,
304             see L for an example.
305              
306             =head1 DESCRIPTION
307              
308             DBD::Mem is a database management system that works right out of the box.
309             If you have a standard installation of Perl and DBI you can begin creating,
310             accessing, and modifying simple database tables without any further modules.
311             You can add other modules (e.g., SQL::Statement) for improved functionality.
312              
313             DBD::Mem doesn't store any data persistently - all data has the lifetime of
314             the instantiated C<$dbh>. The main reason to use DBD::Mem is to use extended
315             features of L where temporary tables are required. One can
316             use DBD::Mem to simulate C or sub-queries.
317              
318             Bundling C with L will allow us further compatibility checks
319             of L beyond the capabilities of L and
320             L. This will ensure DBI provided basis for drivers like
321             L or L are better prepared and tested for
322             not-file based backends.
323              
324             =head2 Metadata
325              
326             There're no new meta data introduced by C. See
327             L for full description.
328              
329             =head1 GETTING HELP, MAKING SUGGESTIONS, AND REPORTING BUGS
330              
331             If you need help installing or using DBD::Mem, please write to the DBI
332             users mailing list at L or to the
333             comp.lang.perl.modules newsgroup on usenet. I cannot always answer
334             every question quickly but there are many on the mailing list or in
335             the newsgroup who can.
336              
337             DBD developers for DBD's which rely on DBI::DBD::SqlEngine or DBD::Mem or
338             use one of them as an example are suggested to join the DBI developers
339             mailing list at L and strongly encouraged to join our
340             IRC channel at L.
341              
342             If you have suggestions, ideas for improvements, or bugs to report, please
343             report a bug as described in DBI. Do not mail any of the authors directly,
344             you might not get an answer.
345              
346             When reporting bugs, please send the output of C<< $dbh->mem_versions($table) >>
347             for a table that exhibits the bug and as small a sample as you can make of
348             the code that produces the bug. And of course, patches are welcome, too
349             :-).
350              
351             If you need enhancements quickly, you can get commercial support as
352             described at L or you can contact Jens Rehsack
353             at rehsack@cpan.org for commercial support.
354              
355             =head1 AUTHOR AND COPYRIGHT
356              
357             This module is written by Jens Rehsack < rehsack AT cpan.org >.
358              
359             Copyright (c) 2016- by Jens Rehsack, all rights reserved.
360              
361             You may freely distribute and/or modify this module under the terms of
362             either the GNU General Public License (GPL) or the Artistic License, as
363             specified in the Perl README file.
364              
365             =head1 SEE ALSO
366              
367             L for the Database interface of the Perl Programming Language.
368              
369             L and L for the available SQL engines.
370              
371             L where the implementation is shamelessly stolen from
372             to allow DBI bundled Pure-Perl drivers increase the test coverage.
373              
374             L using C for an incredible fast in-memory database engine.
375              
376             =cut