File Coverage

blib/lib/SQL/Amazon/Tables/Table.pm
Criterion Covered Total %
statement 9 177 5.0
branch 0 84 0.0
condition 0 20 0.0
subroutine 3 39 7.6
pod 0 35 0.0
total 12 355 3.3


line stmt bran cond sub pod time code
1             #
2             # Copyright (c) 2005, Presicient Corp., USA
3             #
4             # Permission is granted to use this software according to the terms of the
5             # Artistic License, as specified in the Perl README file,
6             # with the exception that commercial redistribution, either
7             # electronic or via physical media, as either a standalone package,
8             # or incorporated into a third party product, requires prior
9             # written approval of the author.
10             #
11             # This software is distributed in the hope that it will be useful,
12             # but WITHOUT ANY WARRANTY; without even the implied warranty of
13             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14             #
15             # Presicient Corp. reserves the right to provide support for this software
16             # to individual sites under a separate (possibly fee-based)
17             # agreement.
18             #
19             # History:
20             #
21             # 2005-Jan-27 D. Arnold
22             # Coded.
23             #
24             package SQL::Amazon::Tables::Table;
25              
26 1     1   6 use DBI qw(:sql_types);
  1         2  
  1         421  
27 1     1   6 use strict;
  1         2  
  1         38  
28              
29 1     1   5 use constant AMZN_CACHE_TIME_LIMIT => 1800;
  1         2  
  1         2994  
30              
31 0     0 0   sub get_time_limit { return AMZN_CACHE_TIME_LIMIT; }
32              
33             sub new {
34 0     0 0   my ($class, $metadata) = @_;
35 0 0         my $obj = $metadata ? { %$metadata } : {};
36 0           $obj->{_rows} = {};
37 0           $obj->{_readonly} = 1;
38 0           $obj->{_request_map} = {};
39              
40 0 0         if ($metadata) {
41 0           $obj->{col_names} = $obj->{NAME};
42 0           my %colnums = ();
43 0           $colnums{$obj->{NAME}[$_]} = $_
44 0           foreach (0..$#{$obj->{NAME}});
45              
46 0           $obj->{col_nums} = \%colnums;
47             }
48 0           $obj->{_key_cols} = [ $obj->{col_nums}{ASIN} ];
49            
50 0           bless $obj, $class;
51 0           return $obj;
52             }
53             sub name {
54 0     0 0   my $obj = shift;
55              
56 0 0         return (ref $obj=~/.+::(\S+)$/) ? $1 : undef;
57             }
58              
59 0     0 0   sub is_readonly { return shift->{_readonly}; }
60 0     0 0   sub is_cacheonly { return shift->{_cache_only}; }
61 0     0 0   sub is_local { return shift->{_local}; }
62 0     0 0   sub debug { shift->{_debug} = shift; }
63              
64             sub commit {
65 0     0 0   my ($obj, $sql, $table) = @_;
66 0           1;
67             }
68              
69             sub rollback {
70 0     0 0   my ($obj, $sql, $table) = @_;
71 0           1;
72             }
73              
74             sub trim {
75 0     0 0   my $x = shift;
76 0           $x =~ s/^\s+//;
77 0           $x =~ s/\s+$//;
78 0           $x;
79             }
80             sub get_metadata {
81 0     0 0   my $obj = shift;
82            
83             return {
84 0           NAME => $obj->{NAME},
85             TYPE => $obj->{TYPE},
86             PRECISION => $obj->{PRECISION},
87             SCALE => $obj->{SCALE},
88             NULLABLE => $obj->{NULLABLE}
89             };
90             }
91             sub fetch {
92 0     0 0   my($obj, $key) = @_;
93              
94             return undef
95 0 0         unless exists $obj->{_rows}{$key};
96 0 0         unless (ref $obj->{_rows}{$key}) {
97 0           $key .= "\0" . '1';
98             return undef
99 0 0         unless exists $obj->{_rows}{$key};
100             }
101              
102 0 0         return $obj->{_rows}{$key}[0] > time() ?
103             $obj->{_rows}{$key}[1] : undef;
104             }
105             sub fetch_all {
106 0     0 0   my ($obj, $reqids) = @_;
107              
108 0           my $rows = $obj->{_rows};
109 0           my $reqmap = $obj->{_request_map};
110 0 0         $reqids = { %$reqmap }
111             unless defined($reqids);
112              
113 0           my %keys = ();
114 0           foreach my $reqid (keys %$reqids) {
115 0           my $reqkeys = $reqmap->{$reqid};
116 0           foreach (keys %$reqkeys) {
117 0 0         delete $reqkeys->{$_},
118             next
119             unless defined($rows->{$_});
120              
121             next
122 0 0         unless (ref $rows->{$_});
123              
124 0 0         $keys{$_} = 1,
125             next
126             if ($rows->{$_}[0] > time());
127              
128 0           delete $rows->{$_};
129 0           delete $reqkeys->{$_};# its timed out, get rid of it
130             }
131             }
132 0           my @keys = keys %keys;
133 0           return \@keys;
134             }
135             sub format_date {
136 0     0 0   my $date = shift;
137 0 0         $date = shift
138             if ref $date;
139            
140 0 0         return '****-**-**'
141             unless ($date=~/^(\d{4})-(\d{1,2})(-(\d{1,2}))?$/);
142 0           my ($yr, $mo, $da) = ($1, $2, $4);
143 0 0         $mo = '0' . $mo
144             unless (length($mo) > 1);
145 0 0         $da = defined($da) ?
    0          
146             (length($da) < 2) ? '0' . $da : $da :
147             '01';
148 0 0 0       return '****-**-**'
149             unless (($mo < 13) && ($da < 32));
150              
151 0           return join('-', $yr, $mo, $da);
152             }
153             sub format_money {
154 0     0 0   my $amt = shift;
155 0 0         $amt = shift
156             if ref $amt;
157              
158 0 0         return '*********.**'
159             unless ($amt=~/^-?[0-9]+$/);
160 0 0         $amt = '0' x (3 - length($amt)) . $amt
161             if (length($amt) < 3);
162              
163 0           substr($amt, -2, 0) = '.';
164 0           return $amt;
165             }
166              
167             sub insert {
168 0     0 0   my ($obj, $item, $reqid) = @_;
169 0           my $names = $obj->{NAME};
170 0           my $types = $obj->{TYPE};
171 0           my @row = ();
172              
173             $row[$_] = exists $item->{$names->[$_]} ?
174             (($types->[$_] == SQL_DATE) ?
175             format_date($item->{$names->[$_]}) :
176             ($types->[$_] == SQL_DECIMAL) ?
177             format_money($item->{$names->[$_]}) :
178             $item->{$names->[$_]}) :
179             undef
180 0 0         foreach (0..$#$names);
    0          
    0          
181            
182 0           return $obj->save_row(\@row, $item, $reqid);
183             }
184             sub save_row {
185 0     0 0   my ($obj, $row, $item, $reqid) = @_;
186 0           my @keyvals = ();
187 0           push @keyvals, (defined($row->[$_]) ? $row->[$_] : '')
188 0 0         foreach (@{$obj->{_key_cols}});
189              
190 0           my $key = join("\0", @keyvals);
191 0 0         my $expires = $obj->{_local} ?
192             0x7FFFFFFF :
193             time() + AMZN_CACHE_TIME_LIMIT;
194 0           my $rows = $obj->{_rows};
195 0 0         if ($rows->{$key}) {
196 0 0         if (ref $rows->{$key}) {
197 0 0         if (row_equals($row, $rows->{$key})) {
198 0           $rows->{$key}[0] = $expires;
199             }
200             else {
201 0           my $oldkey = $key . "\0" . '1';
202 0           $rows->{$oldkey} = $rows->{$key};
203 0           $rows->{$key} = 2;
204              
205 0           $key .= "\0" . '2';
206 0           $rows->{$key} = [ $expires, $row ];
207             }
208             }
209             else {
210 0           my $uniquifier = $rows->{$key} + 1;
211 0           $rows->{$key} = $uniquifier;
212 0           $key .= "\0$uniquifier";
213 0           $rows->{$key} = [ $expires, $row ];
214             }
215             }
216             else {
217 0           $rows->{$key} = [ $expires, $row ];
218             }
219 0           $obj->{_request_map}{$reqid}{$key} = 1;
220 0 0 0       $obj->trace_insert($row, $item)
221             if $obj->{_debug} && defined($item);
222              
223 0           return $row;
224             }
225              
226             sub trace_insert {
227 0     0 0   my ($obj, $row, $item) = @_;
228 0           my $names = $obj->{NAME};
229              
230 0           my ($tblname) = (ref $obj=~/::(\w+)$/);
231 0           foreach (@$names) {
232 0 0         warn "[SQL::Amazon::Tables::insert] Column $_ not supplied for table $tblname\n"
233             unless $row->{$_};
234             }
235 0           foreach (keys %$item) {
236 0 0         warn "[SQL::Amazon::Tables::insert] Column $_ (value '$row->{$_}') not recognized for table $tblname\n"
237             unless defined($obj->{col_nums}{$_});
238             }
239 0           return $obj;
240             }
241             sub compute_key {
242 0     0 0   my ($obj, $row) = @_;
243            
244 0           my @keys = ();
245 0           push @keys, uc (defined($row->[$_]) ? $row->[$_] : '')
246 0 0         foreach (@{$obj->{_key_cols}});
247 0           return join("\0", @keys);
248             }
249              
250             sub is_key_column {
251 0     0 0   my ($obj, $colname) = @_;
252            
253 0 0         unless ($colname=~/^[0-9]+$/) {
254 0           $colname = $obj->{col_nums}{$colname};
255             return undef
256 0 0         unless defined($colname);
257             }
258              
259 0           my $keycols = $obj->{_key_cols};
260 0           foreach (@$keycols) {
261 0 0         return $obj
262             if ($_ == $colname);
263             }
264 0           return undef;
265             }
266              
267             sub spoil {
268 0     0 0   my ($obj, $id) = @_;
269            
270 0           delete $obj->{_rows}{$id};
271 0           return $obj;
272             }
273              
274             sub spoil_all {
275 0     0 0   my $obj = shift;
276            
277 0           $obj->{_rows} = {};
278 0           return $obj;
279             }
280             sub row ($;$) {
281 0     0 0   my($obj, $row) = @_;
282 0 0         if (@_ == 2) {
283 0           $obj->{row} = $row;
284             }
285             else {
286 0 0         $obj->{row} = undef,
287             return undef
288             if ($obj->{_rows}{_currkey}[0] < time());
289 0           return $obj->{row};
290             }
291             }
292              
293             sub column ($$;$) {
294 0     0 0   my($self, $column, $val) = @_;
295 0 0         if (@_ == 3) {
296 0           $self->{row}[$self->{col_nums}{$column}] = $val;
297             } else {
298 0           $self->{row}[$self->{col_nums}{$column}];
299             }
300             }
301              
302             sub column_num ($$) {
303 0     0 0   my($self, $col) = @_;
304 0           $self->{col_nums}{$col};
305             }
306              
307             sub col_names ($) {
308 0     0 0   shift->{col_names};
309             }
310              
311             sub col_nums ($) {
312 0     0 0   shift->{col_nums};
313             }
314             sub fetch_row ($$$) {
315 0     0 0   my($obj, $handle, $row) = @_;
316 0           return undef;
317             }
318              
319             sub push_names ($$$) {
320 0     0 0   my($obj, $data, $names) = @_;
321              
322 0           return 1;
323             }
324              
325             sub push_row ($$$) {
326 0     0 0   my($obj, $data, $fields) = @_;
327              
328 0 0         return undef if $obj->{_readonly};
329 0           my $col_num = $obj->{col_nums};
330 0           my @keyvals = ();
331 0           push @keyvals, ($fields->[$col_num->{$_}] || '')
332 0   0       foreach (@{$obj->{_key_cols}});
333              
334 0           $obj->{_rows}{join("\0", @keyvals)}[1] = $fields;
335 0           1;
336             }
337              
338             sub seek ($$$$) {
339 0     0 0   my($obj, $data, $pos, $whence) = @_;
340 0           return 1;
341             }
342              
343             sub drop ($$) {
344 0     0 0   my($obj, $data) = @_;
345 0           return undef;
346             }
347              
348             sub truncate ($$) {
349 0     0 0   my ($obj, $data) = @_;
350            
351 0 0         return undef if $obj->{_readonly};
352            
353 0           my $rowcnt = scalar keys %{$obj->{_rows}};
  0            
354 0           $obj->{_rows} = {};
355 0           return $rowcnt;
356             }
357             sub purge_requests {
358 0     0 0   my ($obj, $reqids) = @_;
359            
360 0           my $reqmap = $obj->{_request_map};
361             delete $reqmap->{$_}
362 0           foreach (keys %$reqids);
363 0           return $obj;
364             }
365             sub row_equals {
366 0     0 0   my ($row1, $row2) = @_;
367            
368 0 0         return undef unless ($#$row1 == $#$row2);
369 0           foreach (0..$#$row1) {
370             return undef
371             unless (
372 0 0 0       (defined($row1->[$_]) &&
      0        
      0        
      0        
373             defined($row2->[$_]) &&
374             ($row1->[$_] eq $row1->[$_])
375             ) ||
376             (!defined($row1->[$_]) &&
377             !defined($row2->[$_])
378             )
379             );
380             }
381 0           return 1;
382             }
383 0     0     sub DESTROY { undef; }
384              
385             1;
386